profile
viewpoint

keestux/avr-eclipse-plugin 5

A fork of avr-eclipse

keestux/tuxcap 4

TuxCap Games Framework

keestux/aquamacs-emacs 1

The Aquamacs development repo

keestux/GamePlay 1

An open-source, cross-platform 3D native C++ game framework making it easy to learn and write mobile and desktop games. (Beta)

keestux/gitg 1

A GitX clone for gtk+/GNOME

keestux/linux-2.6 1

Mirror of Linus Torvald's Kernel Tree

keestux/s3fs 1

FUSE-based file system backed by Amazon S3. (Cloned using svn2git)

keestux/sonospy 1

Sonospy is a UPnP control point and Windows Media proxy for the Sonos multi-room audio system.

keestux/arduino-eclipse-plugin 0

A plugin to make programming the arduino in eclipse easy

fork keestux/mdbtools

MDB Tools - Read Access databases on *nix

http://mdbtools.sourceforge.net

fork in 3 days

fork keestux/pandas_access

A tiny, subprocess-based tool for reading a MS Access database (.rdb) as a Pandas DataFrame.

fork in 3 days

issue openedlxc/lxd

Migration operation fails

<!-- Github issues are used for bug reports. For support questions, please use our forum.

Please fill the template below as it will greatly help us track down your issue and reproduce it on our side.
Feel free to remove anything which doesn't apply to you and add more information where it makes sense. -->

Required information

  • Distribution: Ubuntu
  • Distribution version: 20.04
  • The summary output of "lxc info":
  driver: lxc
  driver_version: 4.0.4
  kernel: Linux
  kernel_architecture: x86_64
  kernel_version: 5.4.0-29-generic
  os_name: Ubuntu
  os_version: "20.04"
  project: default
  server: lxd
  server_clustered: true
  server_name: ijssel
  server_pid: 968857
  server_version: "4.6"
  storage: lvm
  storage_version: 2.02.176(2) (2017-11-03) / 1.02.145 (2017-11-03) / 4.41.0

Issue description

Copying/moving a container to another node in a cluster fails.

Steps to reproduce

  1. create a container from an image that is not (yet) present on the cluster
  2. copy / move the container to another node with the --target option
lxc init ubuntu:16.04 c1 --target node1
lxc copy c1 c2 --target node2

What you get is this error

Error: Error transferring instance data: open /var/snap/lxd/common/lxd/images/a45c5b9dfc58b050e96c0f417fc8b851233e684f4e29e5fc0be77bb6b6714761: no such file or directory

When the image is present on the other node, the copy/move succeeds.

lxc init ubuntu:16.04 c3 --target node2
lxc copy c1 c2 --target node2

This will succeed.

created time in 18 days

issue commentlxc/lxd

No progress information during in-cluster copy/move

I don't know about within a cluster. We started using the cluster just recently. So, you're saying with remotes you get verbose, but not within a cluster. If that is so, then it is not intuitive.

keestux

comment created time in 18 days

issue openedlxc/lxd

Verbose option does not output anything

Required information

  • Distribution: Ubuntu
  • Distribution version: 20.04
  • The summary output of "lxc info":
  driver: lxc
  driver_version: 4.0.4
  kernel: Linux
  kernel_architecture: x86_64
  kernel_version: 5.4.0-29-generic
  os_name: Ubuntu
  os_version: "20.04"
  project: default
  server: lxd
  server_clustered: true
  server_name: ijssel
  server_pid: 968857
  server_version: "4.6"
  storage: lvm
  storage_version: 2.02.176(2) (2017-11-03) / 1.02.145 (2017-11-03) / 4.41.0

Issue description

Using --verbose with lxc move or lxc copy does not give progress information as it used to.

Steps to reproduce

Just create a new container and copy or move it to a different node on the cluster (or any other remote)

lxc init ubuntu:18.04 c1
lxc copy --verbose c1 c2 --target luts

created time in 19 days

PullRequestReviewEvent

delete branch keestux/lxd

delete branch : doc-changes

delete time in a month

pull request commentlxc/lxd

doc/storage: no need to escape underscore in bash examples

Like this?

keestux

comment created time in a month

push eventkeestux/lxd

Kees Bakker

commit sha 79d6534ce4e95ef29bce11b5888dbb21246ebf09

doc/storage: no need to escape underscore in bash examples Signed-off-by: Kees Bakker <kees@ijzerbout.nl>

view details

push time in a month

PR opened lxc/lxd

doc/storage: no need to escape underscore in bash examples

Just a minor fix. In the bash examples you should not escape the underscores.

+3 -3

0 comment

1 changed file

pr created time in a month

create barnchkeestux/lxd

branch : doc-changes

created branch time in a month

fork keestux/lxd

Daemon based on liblxc offering a REST API to manage containers

https://linuxcontainers.org/lxd

fork in a month

issue commentRIOT-OS/RIOT

Suspicious code in emCute

BTW. Until now @haukepetersen hasn't replied. :-(

This problem was caught by Coverity Scan. It allows setting it up via Travis or something. But I don't know how to do that. And even we get it to do analysis (at each PR?), it still requires someone to look at the result. Not everyone feels an urge to do that.

keestux

comment created time in a month

Pull request review commentRIOT-OS/RIOT

net: added emCute - introducing MQTT-SN support

+/*+ * 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_emcute+ * @{+ *+ * @file+ * @brief       MQTT-SN implementation+ *+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>+ *+ * @}+ */++#include <string.h>++#include "log.h"+#include "mutex.h"+#include "sched.h"+#include "xtimer.h"+#include "thread_flags.h"++#include "net/emcute.h"+#include "emcute_internal.h"++#define ENABLE_DEBUG        (0)+#include "debug.h"++#define PROTOCOL_VERSION    (0x01)++#define PUB_FLAGS           (EMCUTE_QOS_MASK | EMCUTE_RETAIN)+#define SUB_FLAGS           (EMCUTE_DUP | EMCUTE_QOS_MASK | EMCUTE_TIT_MASK)++#define TFLAGS_RESP         (0x0001)+#define TFLAGS_TIMEOUT      (0x0002)+#define TFLAGS_ANY          (TFLAGS_RESP | TFLAGS_TIMEOUT)+++static const char *cli_id;+static sock_udp_t sock;+static sock_udp_ep_t gateway;++static uint8_t rbuf[EMCUTE_BUFSIZE];+static uint8_t tbuf[EMCUTE_BUFSIZE];++static emcute_sub_t *subs = NULL;++static mutex_t txlock;++static xtimer_t timer;+static uint16_t id_next = 0x1234;+static volatile uint8_t waiton = 0xff;+static volatile uint16_t waitonid = 0;+static volatile int result;++static inline uint16_t get_u16(const uint8_t *buf)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    return (uint16_t)((buf[0] << 8) | buf[1]);+#else+    return (uint16_t)((buf[1] << 8) | buf[0]);+#endif+}++static inline void set_u16(uint8_t *buf, uint16_t val)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    buf[0] = (uint8_t)(val >> 8);+    buf[1] = (uint8_t)(val & 0xff);+#else+    buf[0] = (uint8_t)(val & 0xff);+    buf[1] = (uint8_t)(val >> 8);+#endif+}++static int set_len(uint8_t *buf, size_t len)+{+    if (len < (0xff - 7)) {+        buf[0] = len + 1;+        return 1;+    }+    else {+        buf[0] = 0x01;+        set_u16(&tbuf[1], (uint16_t)(len + 3));+        return 3;+    }+}++static int get_len(uint8_t *buf, uint16_t *len)+{+    if (buf[0] != 0x01) {+        *len = (uint16_t)buf[0];+        return 1;+    }+    else {+        *len = get_u16(&buf[1]);+        return 3;+    }+}++static void time_evt(void *arg)+{+    thread_flags_set((thread_t *)arg, TFLAGS_TIMEOUT);+}++static int syncsend(uint8_t resp, size_t len, bool unlock)+{+    int res = EMCUTE_TIMEOUT;+    waiton = resp;+    timer.arg = (void *)sched_active_thread;+    /* clear flags, in case the timer was triggered last time right before the+     * remove was called */+    thread_flags_clear(TFLAGS_ANY);++    for (unsigned retries = 0; retries < EMCUTE_N_RETRY; retries++) {+        DEBUG("[emcute] syncsend: sending round %i\n", retries);+        sock_udp_send(&sock, tbuf, len, &gateway);++        xtimer_set(&timer, (EMCUTE_T_RETRY * US_PER_SEC));+        thread_flags_t flags = thread_flags_wait_any(TFLAGS_ANY);+        if (flags & TFLAGS_RESP) {+            DEBUG("[emcute] syncsend: got response [%i]\n", result);+            xtimer_remove(&timer);+            res = result;+            retries = EMCUTE_N_RETRY;+        }+    }++    /* cleanup sync state */+    waiton = 0xff;+    if (unlock) {+        mutex_unlock(&txlock);+    }+    return res;+}++static void on_disconnect(void)+{+    if (waiton == DISCONNECT) {+        gateway.port = 0;+        result = EMCUTE_OK;+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_ack(uint8_t type, int id_pos, int ret_pos, int res_pos)+{+    if ((waiton == type) && (!id_pos || (waitonid == get_u16(&rbuf[id_pos])))) {+        if (!ret_pos || (rbuf[ret_pos] == ACCEPT)) {+            if (res_pos == 0) {+                result = EMCUTE_OK;+            } else {+                result = (int)get_u16(&rbuf[res_pos]);+            }+        } else {+            result = EMCUTE_REJECT;+        }+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_publish(void)+{+    emcute_sub_t *sub;+    uint16_t len;+    int pos = get_len(rbuf, &len);+    uint16_t tid = get_u16(&rbuf[pos + 2]);++    /* allocate a response packet */+    uint8_t buf[7] = { 7, PUBACK, 0, 0, 0, 0, ACCEPT };+    /* and populate message ID and topic ID fields */+    memcpy(&buf[2], &rbuf[3], 4);++    /* return error code in case we don't support/understand active flags. So+     * far we only understand QoS 1... */+    if (rbuf[2] & ~(EMCUTE_QOS_1 | EMCUTE_TIT_SHORT)) {+        buf[6] = REJ_NOTSUP;+        sock_udp_send(&sock, &buf, 7, &gateway);+        return;+    }++    /* find the registered topic */+    for (sub = subs; sub && (sub->topic.id != tid); sub = sub->next) {}+    if (sub == NULL) {+        buf[6] = REJ_INVTID;+        sock_udp_send(&sock, &buf, 7, &gateway);+        DEBUG("[emcute] on pub: no subscription found\n");+    }+    else {+        if (rbuf[2] & EMCUTE_QOS_1) {+            sock_udp_send(&sock, &buf, 7, &gateway);+        }+        DEBUG("[emcute] on pub: got %i bytes of data\n", (int)(len - pos - 6));+        sub->cb(&sub->topic, &rbuf[pos + 6], (size_t)(len - pos - 6));+    }+}++static void on_pingreq(sock_udp_ep_t *remote)+{+    /* @todo    respond with a PINGRESP only if the PINGREQ came from the+     *          connected gateway -> see spec v1.2, section 6.11 */+    uint8_t buf[2] = { 2, PINGRESP };+    sock_udp_send(&sock, &buf, 2, remote);+}++static void on_pingresp(void)+{+    /** @todo: trigger update something like a 'last seen' value */+}++static void send_ping(void)+{+    if (gateway.port != 0) {+        uint8_t buf[2] = { 2, PINGREQ };+        sock_udp_send(&sock, &buf, 2, &gateway);+    }+}++int emcute_con(sock_udp_ep_t *remote, bool clean, const char *will_topic,+               const void *will_msg, size_t will_msg_len, unsigned will_flags)+{+    int res;+    size_t len;++    assert(!will_topic || (will_topic && will_msg && !(will_flags & ~PUB_FLAGS)));++    mutex_lock(&txlock);++    /* check for existing connections and copy given UDP endpoint */+    if (gateway.port != 0) {+        return EMCUTE_NOGW;+    }+    memcpy(&gateway, remote, sizeof(sock_udp_ep_t));++    /* figure out which flags to set */+    uint8_t flags = (clean) ? EMCUTE_CS : 0;+    if (will_topic) {+        flags |= EMCUTE_WILL;+    }++    /* compute packet size */+    len = (strlen(cli_id) + 6);+    tbuf[0] = (uint8_t)len;+    tbuf[1] = CONNECT;+    tbuf[2] = flags;+    tbuf[3] = PROTOCOL_VERSION;+    set_u16(&tbuf[4], EMCUTE_KEEPALIVE);+    memcpy(&tbuf[6], cli_id, strlen(cli_id));++    /* configure 'state machine' and send the connection request */+    if (will_topic) {+        size_t topic_len = strlen(will_topic);+        if ((topic_len > EMCUTE_TOPIC_MAXLEN) ||+            ((will_msg_len + 4) > EMCUTE_BUFSIZE)) {+            gateway.port = 0;+            return EMCUTE_OVERFLOW;+        }++        res = syncsend(WILLTOPICREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* now send WILLTOPIC */+        int pos = set_len(tbuf, (topic_len + 2));+        len = (pos + topic_len + 2);+        tbuf[pos++] = WILLTOPIC;+        tbuf[pos++] = will_flags;+        memcpy(&tbuf[pos], will_topic, strlen(will_topic));++        res = syncsend(WILLMSGREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* and WILLMSG afterwards */+        pos = set_len(tbuf, (will_msg_len + 1));+        len = (pos + will_msg_len + 1);+        tbuf[pos++] = WILLMSG;+        memcpy(&tbuf[pos], will_msg, will_msg_len);+    }++    res = syncsend(CONNACK, len, true);+    if (res != EMCUTE_OK) {+        gateway.port = 0;+    }+    return res;+}++int emcute_discon(void)+{+    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = 2;+    tbuf[1] = DISCONNECT;++    return syncsend(DISCONNECT, 2, true);+}++int emcute_reg(emcute_topic_t *topic)+{+    assert(topic && topic->name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(topic->name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(topic->name) + 6);+    tbuf[1] = REGISTER;+    set_u16(&tbuf[2], 0);+    set_u16(&tbuf[4], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[6], topic->name, strlen(topic->name));++    int res = syncsend(REGACK, (size_t)tbuf[0], true);+    if (res > 0) {+        topic->id = (uint16_t)res;+        res = EMCUTE_OK;+    }+    return res;+}++int emcute_pub(emcute_topic_t *topic, const void *data, size_t len,+               unsigned flags)+{+    int res = EMCUTE_OK;++    assert((topic->id != 0) && data && (len > 0) && !(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len >= (EMCUTE_BUFSIZE - 9)) {+        return EMCUTE_OVERFLOW;+    }+    if (flags & EMCUTE_QOS_2) {+        return EMCUTE_NOTSUP;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 6));+    len += (pos + 6);+    tbuf[pos++] = PUBLISH;+    tbuf[pos++] = flags;+    set_u16(&tbuf[pos], topic->id);+    pos += 2;+    set_u16(&tbuf[pos], id_next);+    waitonid = id_next++;+    pos += 2;+    memcpy(&tbuf[pos], data, len);++    if (flags & EMCUTE_QOS_1) {+        res = syncsend(PUBACK, len, true);+    }+    else {+        sock_udp_send(&sock, tbuf, len, &gateway);+        mutex_unlock(&txlock);+    }++    return res;+}++int emcute_sub(emcute_sub_t *sub, unsigned flags)+{+    assert(sub && (sub->cb) && (sub->topic.name) && !(flags & ~SUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(sub->topic.name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = SUBSCRIBE;+    tbuf[2] = flags;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(SUBACK, (size_t)tbuf[0], false);+    if (res > 0) {+        DEBUG("[emcute] sub: success, topic id is %i\n", res);+        sub->topic.id = res;++        /* check if subscription is already in the list, only insert if not*/+        emcute_sub_t *s;+        for (s = subs; s && (s != sub); s = s->next) {}+        if (!s) {+            sub->next = subs;+            subs = sub;+            res = EMCUTE_OK;+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_unsub(emcute_sub_t *sub)+{+    assert(sub && sub->topic.name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = UNSUBSCRIBE;+    tbuf[2] = 0;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(UNSUBACK, (size_t)tbuf[0], false);+    if (res == EMCUTE_OK) {+        if (subs == sub) {+            subs = sub->next;+        }+        else {+            emcute_sub_t *s;+            for (s = subs; s; s = s->next) {+                if (s->next == sub) {+                    s->next = sub->next;+                    break;+                }+            }+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_willupd_topic(const char *topic, unsigned flags)+{+    assert(!(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (topic && (strlen(topic) > EMCUTE_TOPIC_MAXLEN)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[1] = WILLTOPICUPD;+    if (!topic) {+        tbuf[0] = 2;+    }+    else {+        tbuf[0] = (strlen(topic) + 3);+        tbuf[2] = flags;+        memcpy(&tbuf[3], topic, strlen(topic));+    }++    return syncsend(WILLTOPICRESP, (size_t)tbuf[0], true);+}++int emcute_willupd_msg(const void *data, size_t len)+{+    assert(data && (len > 0));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len > (EMCUTE_BUFSIZE - 4)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 1));+    len += (pos + 1);

See issue #15028 to discuss this further

haukepetersen

comment created time in a month

PullRequestReviewEvent

issue openedRIOT-OS/RIOT

Suspicious code in emCute

In PR #6633, the following code was added. And the code triggers a finding by Coverity Scan. sys/net/application_layer/emcute/emcute.c

int emcute_willupd_msg(const void *data, size_t len)
{
    assert(data && (len > 0));

    if (gateway.port == 0) {
        return EMCUTE_NOGW;
    }
    if (len > (EMCUTE_BUFSIZE - 4)) {
        return EMCUTE_OVERFLOW;
    }

    mutex_lock(&txlock);

    size_t pos = set_len(tbuf, (len + 1));
    len += (pos + 1);                                      <<<====
    tbuf[pos++] = WILLMSGUPD;
    memcpy(&tbuf[pos], data, len);

    return syncsend(WILLMSGRESP, len, true);
}

There is a statement len += (pos + 1); which I think should not be there.

If it can be explained that the statement is correct, then there is a buffer overflow if len is greater than EMCUTE_BUFSIZE - 8. And, if the statement is correct, I would like to understand why.

created time in a month

Pull request review commentRIOT-OS/RIOT

net: added emCute - introducing MQTT-SN support

+/*+ * 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_emcute+ * @{+ *+ * @file+ * @brief       MQTT-SN implementation+ *+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>+ *+ * @}+ */++#include <string.h>++#include "log.h"+#include "mutex.h"+#include "sched.h"+#include "xtimer.h"+#include "thread_flags.h"++#include "net/emcute.h"+#include "emcute_internal.h"++#define ENABLE_DEBUG        (0)+#include "debug.h"++#define PROTOCOL_VERSION    (0x01)++#define PUB_FLAGS           (EMCUTE_QOS_MASK | EMCUTE_RETAIN)+#define SUB_FLAGS           (EMCUTE_DUP | EMCUTE_QOS_MASK | EMCUTE_TIT_MASK)++#define TFLAGS_RESP         (0x0001)+#define TFLAGS_TIMEOUT      (0x0002)+#define TFLAGS_ANY          (TFLAGS_RESP | TFLAGS_TIMEOUT)+++static const char *cli_id;+static sock_udp_t sock;+static sock_udp_ep_t gateway;++static uint8_t rbuf[EMCUTE_BUFSIZE];+static uint8_t tbuf[EMCUTE_BUFSIZE];++static emcute_sub_t *subs = NULL;++static mutex_t txlock;++static xtimer_t timer;+static uint16_t id_next = 0x1234;+static volatile uint8_t waiton = 0xff;+static volatile uint16_t waitonid = 0;+static volatile int result;++static inline uint16_t get_u16(const uint8_t *buf)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    return (uint16_t)((buf[0] << 8) | buf[1]);+#else+    return (uint16_t)((buf[1] << 8) | buf[0]);+#endif+}++static inline void set_u16(uint8_t *buf, uint16_t val)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    buf[0] = (uint8_t)(val >> 8);+    buf[1] = (uint8_t)(val & 0xff);+#else+    buf[0] = (uint8_t)(val & 0xff);+    buf[1] = (uint8_t)(val >> 8);+#endif+}++static int set_len(uint8_t *buf, size_t len)+{+    if (len < (0xff - 7)) {+        buf[0] = len + 1;+        return 1;+    }+    else {+        buf[0] = 0x01;+        set_u16(&tbuf[1], (uint16_t)(len + 3));+        return 3;+    }+}++static int get_len(uint8_t *buf, uint16_t *len)+{+    if (buf[0] != 0x01) {+        *len = (uint16_t)buf[0];+        return 1;+    }+    else {+        *len = get_u16(&buf[1]);+        return 3;+    }+}++static void time_evt(void *arg)+{+    thread_flags_set((thread_t *)arg, TFLAGS_TIMEOUT);+}++static int syncsend(uint8_t resp, size_t len, bool unlock)+{+    int res = EMCUTE_TIMEOUT;+    waiton = resp;+    timer.arg = (void *)sched_active_thread;+    /* clear flags, in case the timer was triggered last time right before the+     * remove was called */+    thread_flags_clear(TFLAGS_ANY);++    for (unsigned retries = 0; retries < EMCUTE_N_RETRY; retries++) {+        DEBUG("[emcute] syncsend: sending round %i\n", retries);+        sock_udp_send(&sock, tbuf, len, &gateway);++        xtimer_set(&timer, (EMCUTE_T_RETRY * US_PER_SEC));+        thread_flags_t flags = thread_flags_wait_any(TFLAGS_ANY);+        if (flags & TFLAGS_RESP) {+            DEBUG("[emcute] syncsend: got response [%i]\n", result);+            xtimer_remove(&timer);+            res = result;+            retries = EMCUTE_N_RETRY;+        }+    }++    /* cleanup sync state */+    waiton = 0xff;+    if (unlock) {+        mutex_unlock(&txlock);+    }+    return res;+}++static void on_disconnect(void)+{+    if (waiton == DISCONNECT) {+        gateway.port = 0;+        result = EMCUTE_OK;+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_ack(uint8_t type, int id_pos, int ret_pos, int res_pos)+{+    if ((waiton == type) && (!id_pos || (waitonid == get_u16(&rbuf[id_pos])))) {+        if (!ret_pos || (rbuf[ret_pos] == ACCEPT)) {+            if (res_pos == 0) {+                result = EMCUTE_OK;+            } else {+                result = (int)get_u16(&rbuf[res_pos]);+            }+        } else {+            result = EMCUTE_REJECT;+        }+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_publish(void)+{+    emcute_sub_t *sub;+    uint16_t len;+    int pos = get_len(rbuf, &len);+    uint16_t tid = get_u16(&rbuf[pos + 2]);++    /* allocate a response packet */+    uint8_t buf[7] = { 7, PUBACK, 0, 0, 0, 0, ACCEPT };+    /* and populate message ID and topic ID fields */+    memcpy(&buf[2], &rbuf[3], 4);++    /* return error code in case we don't support/understand active flags. So+     * far we only understand QoS 1... */+    if (rbuf[2] & ~(EMCUTE_QOS_1 | EMCUTE_TIT_SHORT)) {+        buf[6] = REJ_NOTSUP;+        sock_udp_send(&sock, &buf, 7, &gateway);+        return;+    }++    /* find the registered topic */+    for (sub = subs; sub && (sub->topic.id != tid); sub = sub->next) {}+    if (sub == NULL) {+        buf[6] = REJ_INVTID;+        sock_udp_send(&sock, &buf, 7, &gateway);+        DEBUG("[emcute] on pub: no subscription found\n");+    }+    else {+        if (rbuf[2] & EMCUTE_QOS_1) {+            sock_udp_send(&sock, &buf, 7, &gateway);+        }+        DEBUG("[emcute] on pub: got %i bytes of data\n", (int)(len - pos - 6));+        sub->cb(&sub->topic, &rbuf[pos + 6], (size_t)(len - pos - 6));+    }+}++static void on_pingreq(sock_udp_ep_t *remote)+{+    /* @todo    respond with a PINGRESP only if the PINGREQ came from the+     *          connected gateway -> see spec v1.2, section 6.11 */+    uint8_t buf[2] = { 2, PINGRESP };+    sock_udp_send(&sock, &buf, 2, remote);+}++static void on_pingresp(void)+{+    /** @todo: trigger update something like a 'last seen' value */+}++static void send_ping(void)+{+    if (gateway.port != 0) {+        uint8_t buf[2] = { 2, PINGREQ };+        sock_udp_send(&sock, &buf, 2, &gateway);+    }+}++int emcute_con(sock_udp_ep_t *remote, bool clean, const char *will_topic,+               const void *will_msg, size_t will_msg_len, unsigned will_flags)+{+    int res;+    size_t len;++    assert(!will_topic || (will_topic && will_msg && !(will_flags & ~PUB_FLAGS)));++    mutex_lock(&txlock);++    /* check for existing connections and copy given UDP endpoint */+    if (gateway.port != 0) {+        return EMCUTE_NOGW;+    }+    memcpy(&gateway, remote, sizeof(sock_udp_ep_t));++    /* figure out which flags to set */+    uint8_t flags = (clean) ? EMCUTE_CS : 0;+    if (will_topic) {+        flags |= EMCUTE_WILL;+    }++    /* compute packet size */+    len = (strlen(cli_id) + 6);+    tbuf[0] = (uint8_t)len;+    tbuf[1] = CONNECT;+    tbuf[2] = flags;+    tbuf[3] = PROTOCOL_VERSION;+    set_u16(&tbuf[4], EMCUTE_KEEPALIVE);+    memcpy(&tbuf[6], cli_id, strlen(cli_id));++    /* configure 'state machine' and send the connection request */+    if (will_topic) {+        size_t topic_len = strlen(will_topic);+        if ((topic_len > EMCUTE_TOPIC_MAXLEN) ||+            ((will_msg_len + 4) > EMCUTE_BUFSIZE)) {+            gateway.port = 0;+            return EMCUTE_OVERFLOW;+        }++        res = syncsend(WILLTOPICREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* now send WILLTOPIC */+        int pos = set_len(tbuf, (topic_len + 2));+        len = (pos + topic_len + 2);+        tbuf[pos++] = WILLTOPIC;+        tbuf[pos++] = will_flags;+        memcpy(&tbuf[pos], will_topic, strlen(will_topic));++        res = syncsend(WILLMSGREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* and WILLMSG afterwards */+        pos = set_len(tbuf, (will_msg_len + 1));+        len = (pos + will_msg_len + 1);+        tbuf[pos++] = WILLMSG;+        memcpy(&tbuf[pos], will_msg, will_msg_len);+    }++    res = syncsend(CONNACK, len, true);+    if (res != EMCUTE_OK) {+        gateway.port = 0;+    }+    return res;+}++int emcute_discon(void)+{+    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = 2;+    tbuf[1] = DISCONNECT;++    return syncsend(DISCONNECT, 2, true);+}++int emcute_reg(emcute_topic_t *topic)+{+    assert(topic && topic->name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(topic->name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(topic->name) + 6);+    tbuf[1] = REGISTER;+    set_u16(&tbuf[2], 0);+    set_u16(&tbuf[4], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[6], topic->name, strlen(topic->name));++    int res = syncsend(REGACK, (size_t)tbuf[0], true);+    if (res > 0) {+        topic->id = (uint16_t)res;+        res = EMCUTE_OK;+    }+    return res;+}++int emcute_pub(emcute_topic_t *topic, const void *data, size_t len,+               unsigned flags)+{+    int res = EMCUTE_OK;++    assert((topic->id != 0) && data && (len > 0) && !(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len >= (EMCUTE_BUFSIZE - 9)) {+        return EMCUTE_OVERFLOW;+    }+    if (flags & EMCUTE_QOS_2) {+        return EMCUTE_NOTSUP;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 6));+    len += (pos + 6);+    tbuf[pos++] = PUBLISH;+    tbuf[pos++] = flags;+    set_u16(&tbuf[pos], topic->id);+    pos += 2;+    set_u16(&tbuf[pos], id_next);+    waitonid = id_next++;+    pos += 2;+    memcpy(&tbuf[pos], data, len);++    if (flags & EMCUTE_QOS_1) {+        res = syncsend(PUBACK, len, true);+    }+    else {+        sock_udp_send(&sock, tbuf, len, &gateway);+        mutex_unlock(&txlock);+    }++    return res;+}++int emcute_sub(emcute_sub_t *sub, unsigned flags)+{+    assert(sub && (sub->cb) && (sub->topic.name) && !(flags & ~SUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(sub->topic.name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = SUBSCRIBE;+    tbuf[2] = flags;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(SUBACK, (size_t)tbuf[0], false);+    if (res > 0) {+        DEBUG("[emcute] sub: success, topic id is %i\n", res);+        sub->topic.id = res;++        /* check if subscription is already in the list, only insert if not*/+        emcute_sub_t *s;+        for (s = subs; s && (s != sub); s = s->next) {}+        if (!s) {+            sub->next = subs;+            subs = sub;+            res = EMCUTE_OK;+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_unsub(emcute_sub_t *sub)+{+    assert(sub && sub->topic.name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = UNSUBSCRIBE;+    tbuf[2] = 0;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(UNSUBACK, (size_t)tbuf[0], false);+    if (res == EMCUTE_OK) {+        if (subs == sub) {+            subs = sub->next;+        }+        else {+            emcute_sub_t *s;+            for (s = subs; s; s = s->next) {+                if (s->next == sub) {+                    s->next = sub->next;+                    break;+                }+            }+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_willupd_topic(const char *topic, unsigned flags)+{+    assert(!(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (topic && (strlen(topic) > EMCUTE_TOPIC_MAXLEN)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[1] = WILLTOPICUPD;+    if (!topic) {+        tbuf[0] = 2;+    }+    else {+        tbuf[0] = (strlen(topic) + 3);+        tbuf[2] = flags;+        memcpy(&tbuf[3], topic, strlen(topic));+    }++    return syncsend(WILLTOPICRESP, (size_t)tbuf[0], true);+}++int emcute_willupd_msg(const void *data, size_t len)+{+    assert(data && (len > 0));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len > (EMCUTE_BUFSIZE - 4)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 1));+    len += (pos + 1);

@haukepetersen any comment to this?

haukepetersen

comment created time in 2 months

PullRequestReviewEvent

Pull request review commentRIOT-OS/RIOT

net: added emCute - introducing MQTT-SN support

+/*+ * 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_emcute+ * @{+ *+ * @file+ * @brief       MQTT-SN implementation+ *+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>+ *+ * @}+ */++#include <string.h>++#include "log.h"+#include "mutex.h"+#include "sched.h"+#include "xtimer.h"+#include "thread_flags.h"++#include "net/emcute.h"+#include "emcute_internal.h"++#define ENABLE_DEBUG        (0)+#include "debug.h"++#define PROTOCOL_VERSION    (0x01)++#define PUB_FLAGS           (EMCUTE_QOS_MASK | EMCUTE_RETAIN)+#define SUB_FLAGS           (EMCUTE_DUP | EMCUTE_QOS_MASK | EMCUTE_TIT_MASK)++#define TFLAGS_RESP         (0x0001)+#define TFLAGS_TIMEOUT      (0x0002)+#define TFLAGS_ANY          (TFLAGS_RESP | TFLAGS_TIMEOUT)+++static const char *cli_id;+static sock_udp_t sock;+static sock_udp_ep_t gateway;++static uint8_t rbuf[EMCUTE_BUFSIZE];+static uint8_t tbuf[EMCUTE_BUFSIZE];++static emcute_sub_t *subs = NULL;++static mutex_t txlock;++static xtimer_t timer;+static uint16_t id_next = 0x1234;+static volatile uint8_t waiton = 0xff;+static volatile uint16_t waitonid = 0;+static volatile int result;++static inline uint16_t get_u16(const uint8_t *buf)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    return (uint16_t)((buf[0] << 8) | buf[1]);+#else+    return (uint16_t)((buf[1] << 8) | buf[0]);+#endif+}++static inline void set_u16(uint8_t *buf, uint16_t val)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    buf[0] = (uint8_t)(val >> 8);+    buf[1] = (uint8_t)(val & 0xff);+#else+    buf[0] = (uint8_t)(val & 0xff);+    buf[1] = (uint8_t)(val >> 8);+#endif+}++static int set_len(uint8_t *buf, size_t len)+{+    if (len < (0xff - 7)) {+        buf[0] = len + 1;+        return 1;+    }+    else {+        buf[0] = 0x01;+        set_u16(&tbuf[1], (uint16_t)(len + 3));+        return 3;+    }+}++static int get_len(uint8_t *buf, uint16_t *len)+{+    if (buf[0] != 0x01) {+        *len = (uint16_t)buf[0];+        return 1;+    }+    else {+        *len = get_u16(&buf[1]);+        return 3;+    }+}++static void time_evt(void *arg)+{+    thread_flags_set((thread_t *)arg, TFLAGS_TIMEOUT);+}++static int syncsend(uint8_t resp, size_t len, bool unlock)+{+    int res = EMCUTE_TIMEOUT;+    waiton = resp;+    timer.arg = (void *)sched_active_thread;+    /* clear flags, in case the timer was triggered last time right before the+     * remove was called */+    thread_flags_clear(TFLAGS_ANY);++    for (unsigned retries = 0; retries < EMCUTE_N_RETRY; retries++) {+        DEBUG("[emcute] syncsend: sending round %i\n", retries);+        sock_udp_send(&sock, tbuf, len, &gateway);++        xtimer_set(&timer, (EMCUTE_T_RETRY * US_PER_SEC));+        thread_flags_t flags = thread_flags_wait_any(TFLAGS_ANY);+        if (flags & TFLAGS_RESP) {+            DEBUG("[emcute] syncsend: got response [%i]\n", result);+            xtimer_remove(&timer);+            res = result;+            retries = EMCUTE_N_RETRY;+        }+    }++    /* cleanup sync state */+    waiton = 0xff;+    if (unlock) {+        mutex_unlock(&txlock);+    }+    return res;+}++static void on_disconnect(void)+{+    if (waiton == DISCONNECT) {+        gateway.port = 0;+        result = EMCUTE_OK;+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_ack(uint8_t type, int id_pos, int ret_pos, int res_pos)+{+    if ((waiton == type) && (!id_pos || (waitonid == get_u16(&rbuf[id_pos])))) {+        if (!ret_pos || (rbuf[ret_pos] == ACCEPT)) {+            if (res_pos == 0) {+                result = EMCUTE_OK;+            } else {+                result = (int)get_u16(&rbuf[res_pos]);+            }+        } else {+            result = EMCUTE_REJECT;+        }+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_publish(void)+{+    emcute_sub_t *sub;+    uint16_t len;+    int pos = get_len(rbuf, &len);+    uint16_t tid = get_u16(&rbuf[pos + 2]);++    /* allocate a response packet */+    uint8_t buf[7] = { 7, PUBACK, 0, 0, 0, 0, ACCEPT };+    /* and populate message ID and topic ID fields */+    memcpy(&buf[2], &rbuf[3], 4);++    /* return error code in case we don't support/understand active flags. So+     * far we only understand QoS 1... */+    if (rbuf[2] & ~(EMCUTE_QOS_1 | EMCUTE_TIT_SHORT)) {+        buf[6] = REJ_NOTSUP;+        sock_udp_send(&sock, &buf, 7, &gateway);+        return;+    }++    /* find the registered topic */+    for (sub = subs; sub && (sub->topic.id != tid); sub = sub->next) {}+    if (sub == NULL) {+        buf[6] = REJ_INVTID;+        sock_udp_send(&sock, &buf, 7, &gateway);+        DEBUG("[emcute] on pub: no subscription found\n");+    }+    else {+        if (rbuf[2] & EMCUTE_QOS_1) {+            sock_udp_send(&sock, &buf, 7, &gateway);+        }+        DEBUG("[emcute] on pub: got %i bytes of data\n", (int)(len - pos - 6));+        sub->cb(&sub->topic, &rbuf[pos + 6], (size_t)(len - pos - 6));+    }+}++static void on_pingreq(sock_udp_ep_t *remote)+{+    /* @todo    respond with a PINGRESP only if the PINGREQ came from the+     *          connected gateway -> see spec v1.2, section 6.11 */+    uint8_t buf[2] = { 2, PINGRESP };+    sock_udp_send(&sock, &buf, 2, remote);+}++static void on_pingresp(void)+{+    /** @todo: trigger update something like a 'last seen' value */+}++static void send_ping(void)+{+    if (gateway.port != 0) {+        uint8_t buf[2] = { 2, PINGREQ };+        sock_udp_send(&sock, &buf, 2, &gateway);+    }+}++int emcute_con(sock_udp_ep_t *remote, bool clean, const char *will_topic,+               const void *will_msg, size_t will_msg_len, unsigned will_flags)+{+    int res;+    size_t len;++    assert(!will_topic || (will_topic && will_msg && !(will_flags & ~PUB_FLAGS)));++    mutex_lock(&txlock);++    /* check for existing connections and copy given UDP endpoint */+    if (gateway.port != 0) {+        return EMCUTE_NOGW;+    }+    memcpy(&gateway, remote, sizeof(sock_udp_ep_t));++    /* figure out which flags to set */+    uint8_t flags = (clean) ? EMCUTE_CS : 0;+    if (will_topic) {+        flags |= EMCUTE_WILL;+    }++    /* compute packet size */+    len = (strlen(cli_id) + 6);+    tbuf[0] = (uint8_t)len;+    tbuf[1] = CONNECT;+    tbuf[2] = flags;+    tbuf[3] = PROTOCOL_VERSION;+    set_u16(&tbuf[4], EMCUTE_KEEPALIVE);+    memcpy(&tbuf[6], cli_id, strlen(cli_id));++    /* configure 'state machine' and send the connection request */+    if (will_topic) {+        size_t topic_len = strlen(will_topic);+        if ((topic_len > EMCUTE_TOPIC_MAXLEN) ||+            ((will_msg_len + 4) > EMCUTE_BUFSIZE)) {+            gateway.port = 0;+            return EMCUTE_OVERFLOW;+        }++        res = syncsend(WILLTOPICREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* now send WILLTOPIC */+        int pos = set_len(tbuf, (topic_len + 2));+        len = (pos + topic_len + 2);+        tbuf[pos++] = WILLTOPIC;+        tbuf[pos++] = will_flags;+        memcpy(&tbuf[pos], will_topic, strlen(will_topic));++        res = syncsend(WILLMSGREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* and WILLMSG afterwards */+        pos = set_len(tbuf, (will_msg_len + 1));+        len = (pos + will_msg_len + 1);+        tbuf[pos++] = WILLMSG;+        memcpy(&tbuf[pos], will_msg, will_msg_len);+    }++    res = syncsend(CONNACK, len, true);+    if (res != EMCUTE_OK) {+        gateway.port = 0;+    }+    return res;+}++int emcute_discon(void)+{+    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = 2;+    tbuf[1] = DISCONNECT;++    return syncsend(DISCONNECT, 2, true);+}++int emcute_reg(emcute_topic_t *topic)+{+    assert(topic && topic->name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(topic->name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(topic->name) + 6);+    tbuf[1] = REGISTER;+    set_u16(&tbuf[2], 0);+    set_u16(&tbuf[4], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[6], topic->name, strlen(topic->name));++    int res = syncsend(REGACK, (size_t)tbuf[0], true);+    if (res > 0) {+        topic->id = (uint16_t)res;+        res = EMCUTE_OK;+    }+    return res;+}++int emcute_pub(emcute_topic_t *topic, const void *data, size_t len,+               unsigned flags)+{+    int res = EMCUTE_OK;++    assert((topic->id != 0) && data && (len > 0) && !(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len >= (EMCUTE_BUFSIZE - 9)) {+        return EMCUTE_OVERFLOW;+    }+    if (flags & EMCUTE_QOS_2) {+        return EMCUTE_NOTSUP;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 6));+    len += (pos + 6);+    tbuf[pos++] = PUBLISH;+    tbuf[pos++] = flags;+    set_u16(&tbuf[pos], topic->id);+    pos += 2;+    set_u16(&tbuf[pos], id_next);+    waitonid = id_next++;+    pos += 2;+    memcpy(&tbuf[pos], data, len);++    if (flags & EMCUTE_QOS_1) {+        res = syncsend(PUBACK, len, true);+    }+    else {+        sock_udp_send(&sock, tbuf, len, &gateway);+        mutex_unlock(&txlock);+    }++    return res;+}++int emcute_sub(emcute_sub_t *sub, unsigned flags)+{+    assert(sub && (sub->cb) && (sub->topic.name) && !(flags & ~SUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(sub->topic.name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = SUBSCRIBE;+    tbuf[2] = flags;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(SUBACK, (size_t)tbuf[0], false);+    if (res > 0) {+        DEBUG("[emcute] sub: success, topic id is %i\n", res);+        sub->topic.id = res;++        /* check if subscription is already in the list, only insert if not*/+        emcute_sub_t *s;+        for (s = subs; s && (s != sub); s = s->next) {}+        if (!s) {+            sub->next = subs;+            subs = sub;+            res = EMCUTE_OK;+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_unsub(emcute_sub_t *sub)+{+    assert(sub && sub->topic.name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = UNSUBSCRIBE;+    tbuf[2] = 0;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(UNSUBACK, (size_t)tbuf[0], false);+    if (res == EMCUTE_OK) {+        if (subs == sub) {+            subs = sub->next;+        }+        else {+            emcute_sub_t *s;+            for (s = subs; s; s = s->next) {+                if (s->next == sub) {+                    s->next = sub->next;+                    break;+                }+            }+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_willupd_topic(const char *topic, unsigned flags)+{+    assert(!(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (topic && (strlen(topic) > EMCUTE_TOPIC_MAXLEN)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[1] = WILLTOPICUPD;+    if (!topic) {+        tbuf[0] = 2;+    }+    else {+        tbuf[0] = (strlen(topic) + 3);+        tbuf[2] = flags;+        memcpy(&tbuf[3], topic, strlen(topic));+    }++    return syncsend(WILLTOPICRESP, (size_t)tbuf[0], true);+}++int emcute_willupd_msg(const void *data, size_t len)+{+    assert(data && (len > 0));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len > (EMCUTE_BUFSIZE - 4)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 1));+    len += (pos + 1);

Maybe I wasn't clear. My point is that this statement should not be there at all.

len is the length of the data. It does not make sense to increase it by 4. The three bytes for the length field are already copied into tbuf through set_len. Then WILLMSGUPD is copied into the buffer. What is left to do with memcpy is to copy the data with length len. Notice the &tbuf[pos] being the destination of memcpy.

haukepetersen

comment created time in 2 months

PullRequestReviewEvent
PullRequestReviewEvent

issue commentRIOT-OS/RIOT

Return value of gnrc* calls not checked for -1

Sorry for the duplicate. I had totally forgotten that I already created #14961

keestux

comment created time in 2 months

issue openedRIOT-OS/RIOT

Return value of gnrc* calls not checked for -1

Description

The return value of a few gnrc_* functions are used as an index in an array. These functions can return -1, but not all callers check for the -1.

The following are identified by Coverity Scan.

  • sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c:999
  • sys/net/gnrc/network_layer/ipv6/nib/nib.c:919
  • sys/net/gnrc/network_layer/ipv6/nib/nib.c:1051

created time in 2 months

Pull request review commentRIOT-OS/RIOT

gnrc_sock: provide port for sock_ip and sock_udp

+/*+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>+ *+ * 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.+ */++/**+ * @{+ *+ * @file+ * @brief       GNRC implementation of @ref net_sock_ip+ *+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>+ */++#include <errno.h>++#include "byteorder.h"+#include "net/af.h"+#include "net/protnum.h"+#include "net/gnrc/ipv6.h"+#include "net/sock/ip.h"+#include "random.h"++#include "gnrc_sock_internal.h"++int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local,+                    const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags)+{+    assert(sock);+    if ((local != NULL) && (remote != NULL) &&+        (local->netif != SOCK_ADDR_ANY_NETIF) &&+        (remote->netif != SOCK_ADDR_ANY_NETIF) &&+        (local->netif != remote->netif)) {+        return -EINVAL;+    }+    memset(&sock->local, 0, sizeof(sock_ip_t));+    if (local != NULL) {+        if (gnrc_af_not_supported(local->family)) {+            return -EAFNOSUPPORT;+        }+        memcpy(&sock->local, local, sizeof(sock_ip_t));+    }+    memset(&sock->remote, 0, sizeof(sock_ip_t));+    if (remote != NULL) {+        if (gnrc_af_not_supported(remote->family)) {+            return -EAFNOSUPPORT;+        }+        if (gnrc_ep_addr_any(remote)) {+            return -EINVAL;+        }+        memcpy(&sock->remote, remote, sizeof(sock_ip_t));+    }+    gnrc_sock_create(&sock->reg, GNRC_NETTYPE_IPV6,+                     proto);+    sock->flags = flags;+    return 0;+}++void sock_ip_close(sock_ip_t *sock)+{+    assert(sock != NULL);+    gnrc_netreg_unregister(GNRC_NETTYPE_IPV6, &sock->reg.entry);+}++int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *local)+{+    assert(sock && local);+    if (sock->local.family == AF_UNSPEC) {+        return -EADDRNOTAVAIL;+    }+    memcpy(local, &sock->local, sizeof(sock_ip_ep_t));+    return 0;+}++int sock_ip_get_remote(sock_ip_t *sock, sock_ip_ep_t *remote)+{+    assert(sock && remote);+    if (sock->remote.family == AF_UNSPEC) {+        return -ENOTCONN;+    }+    memcpy(remote, &sock->remote, sizeof(sock_ip_ep_t));+    return 0;+}++ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len,+                     uint32_t timeout, sock_ip_ep_t *remote)+{+    gnrc_pktsnip_t *pkt;+    sock_ip_ep_t tmp;+    int res;++    assert((sock != NULL) && (data != NULL) && (max_len > 0));+    if (sock->local.family == 0) {+        return -EADDRNOTAVAIL;+    }+    tmp.family = sock->local.family;+    res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp);+    if (res < 0) {+        return res;+    }+    if (pkt->size > max_len) {+        gnrc_pktbuf_release(pkt);+        return -ENOBUFS;+    }+    if (remote != NULL) {+        /* return remote to possibly block if wrong remote */+        memcpy(remote, &tmp, sizeof(tmp));+    }+    if ((sock->remote.family != AF_UNSPEC) &&   /* check remote end-point if set */+        /* We only have IPv6 for now, so just comparing the whole end point+         * should suffice */+        ((memcmp(&sock->remote.addr, &ipv6_addr_unspecified,+                 sizeof(ipv6_addr_t)) != 0) &&+         (memcmp(&sock->remote.addr, &tmp.addr, sizeof(ipv6_addr_t)) != 0))) {+        gnrc_pktbuf_release(pkt);+        return -EPROTO;+    }+    memcpy(data, pkt->data, pkt->size);+    gnrc_pktbuf_release(pkt);+    return (int)pkt->size;+}++ssize_t sock_ip_send(sock_ip_t *sock, const void *data, size_t len,+                     uint8_t proto, const sock_ip_ep_t *remote)+{+    int res;+    gnrc_pktsnip_t *pkt;+    sock_ip_ep_t local;+    sock_ip_ep_t rem;++    assert((sock != NULL) || (remote != NULL));+    assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */+    if ((remote != NULL) && (sock != NULL) &&+        (sock->local.netif != SOCK_ADDR_ANY_NETIF) &&+        (remote->netif != SOCK_ADDR_ANY_NETIF) &&+        (sock->local.netif != remote->netif)) {+        return -EINVAL;+    }+    if ((remote == NULL) &&+        /* sock can't be NULL as per assertion above */+        (sock->remote.family == AF_UNSPEC)) {+        return -ENOTCONN;+    }+    else if ((remote != NULL) && (gnrc_ep_addr_any(remote))) {+        return -EINVAL;+    }+    /* compiler evaluates lazily so this isn't a redundundant check and cppcheck+     * is being weird here anyways */+    /* cppcheck-suppress nullPointerRedundantCheck */+    /* cppcheck-suppress nullPointer */+    if ((sock == NULL) || (sock->local.family == AF_UNSPEC)) {+        /* no sock or sock currently unbound */+        memset(&local, 0, sizeof(local));+    }+    else {+        if (sock != NULL) {+            proto = (uint8_t)sock->reg.entry.demux_ctx;+        }+        memcpy(&local, &sock->local, sizeof(local));+    }+    if (remote == NULL) {+        /* sock can't be NULL at this point */+        memcpy(&rem, &sock->remote, sizeof(rem));+    }+    else {+        memcpy(&rem, remote, sizeof(rem));+    }+    if ((remote != NULL) && (remote->family == AF_UNSPEC) &&+        (sock->remote.family != AF_UNSPEC)) {+        /* remote was set on create so take its family */+        rem.family = sock->remote.family;+    }

@miri64 The assert above indicates that remote or sock must be non-NULL. At this if statement we check that remote is not NULL. But in that case it is possible that sock is NULL. We don't check that before using sock.

miri64

comment created time in 2 months

PullRequestReviewEvent

create barnchkeestux/RIOT

branch : bugfix-universal-address

created branch time in 2 months

Pull request review commentRIOT-OS/RIOT

net: added emCute - introducing MQTT-SN support

+/*+ * 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_emcute+ * @{+ *+ * @file+ * @brief       MQTT-SN implementation+ *+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>+ *+ * @}+ */++#include <string.h>++#include "log.h"+#include "mutex.h"+#include "sched.h"+#include "xtimer.h"+#include "thread_flags.h"++#include "net/emcute.h"+#include "emcute_internal.h"++#define ENABLE_DEBUG        (0)+#include "debug.h"++#define PROTOCOL_VERSION    (0x01)++#define PUB_FLAGS           (EMCUTE_QOS_MASK | EMCUTE_RETAIN)+#define SUB_FLAGS           (EMCUTE_DUP | EMCUTE_QOS_MASK | EMCUTE_TIT_MASK)++#define TFLAGS_RESP         (0x0001)+#define TFLAGS_TIMEOUT      (0x0002)+#define TFLAGS_ANY          (TFLAGS_RESP | TFLAGS_TIMEOUT)+++static const char *cli_id;+static sock_udp_t sock;+static sock_udp_ep_t gateway;++static uint8_t rbuf[EMCUTE_BUFSIZE];+static uint8_t tbuf[EMCUTE_BUFSIZE];++static emcute_sub_t *subs = NULL;++static mutex_t txlock;++static xtimer_t timer;+static uint16_t id_next = 0x1234;+static volatile uint8_t waiton = 0xff;+static volatile uint16_t waitonid = 0;+static volatile int result;++static inline uint16_t get_u16(const uint8_t *buf)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    return (uint16_t)((buf[0] << 8) | buf[1]);+#else+    return (uint16_t)((buf[1] << 8) | buf[0]);+#endif+}++static inline void set_u16(uint8_t *buf, uint16_t val)+{+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__+    buf[0] = (uint8_t)(val >> 8);+    buf[1] = (uint8_t)(val & 0xff);+#else+    buf[0] = (uint8_t)(val & 0xff);+    buf[1] = (uint8_t)(val >> 8);+#endif+}++static int set_len(uint8_t *buf, size_t len)+{+    if (len < (0xff - 7)) {+        buf[0] = len + 1;+        return 1;+    }+    else {+        buf[0] = 0x01;+        set_u16(&tbuf[1], (uint16_t)(len + 3));+        return 3;+    }+}++static int get_len(uint8_t *buf, uint16_t *len)+{+    if (buf[0] != 0x01) {+        *len = (uint16_t)buf[0];+        return 1;+    }+    else {+        *len = get_u16(&buf[1]);+        return 3;+    }+}++static void time_evt(void *arg)+{+    thread_flags_set((thread_t *)arg, TFLAGS_TIMEOUT);+}++static int syncsend(uint8_t resp, size_t len, bool unlock)+{+    int res = EMCUTE_TIMEOUT;+    waiton = resp;+    timer.arg = (void *)sched_active_thread;+    /* clear flags, in case the timer was triggered last time right before the+     * remove was called */+    thread_flags_clear(TFLAGS_ANY);++    for (unsigned retries = 0; retries < EMCUTE_N_RETRY; retries++) {+        DEBUG("[emcute] syncsend: sending round %i\n", retries);+        sock_udp_send(&sock, tbuf, len, &gateway);++        xtimer_set(&timer, (EMCUTE_T_RETRY * US_PER_SEC));+        thread_flags_t flags = thread_flags_wait_any(TFLAGS_ANY);+        if (flags & TFLAGS_RESP) {+            DEBUG("[emcute] syncsend: got response [%i]\n", result);+            xtimer_remove(&timer);+            res = result;+            retries = EMCUTE_N_RETRY;+        }+    }++    /* cleanup sync state */+    waiton = 0xff;+    if (unlock) {+        mutex_unlock(&txlock);+    }+    return res;+}++static void on_disconnect(void)+{+    if (waiton == DISCONNECT) {+        gateway.port = 0;+        result = EMCUTE_OK;+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_ack(uint8_t type, int id_pos, int ret_pos, int res_pos)+{+    if ((waiton == type) && (!id_pos || (waitonid == get_u16(&rbuf[id_pos])))) {+        if (!ret_pos || (rbuf[ret_pos] == ACCEPT)) {+            if (res_pos == 0) {+                result = EMCUTE_OK;+            } else {+                result = (int)get_u16(&rbuf[res_pos]);+            }+        } else {+            result = EMCUTE_REJECT;+        }+        thread_flags_set((thread_t *)timer.arg, TFLAGS_RESP);+    }+}++static void on_publish(void)+{+    emcute_sub_t *sub;+    uint16_t len;+    int pos = get_len(rbuf, &len);+    uint16_t tid = get_u16(&rbuf[pos + 2]);++    /* allocate a response packet */+    uint8_t buf[7] = { 7, PUBACK, 0, 0, 0, 0, ACCEPT };+    /* and populate message ID and topic ID fields */+    memcpy(&buf[2], &rbuf[3], 4);++    /* return error code in case we don't support/understand active flags. So+     * far we only understand QoS 1... */+    if (rbuf[2] & ~(EMCUTE_QOS_1 | EMCUTE_TIT_SHORT)) {+        buf[6] = REJ_NOTSUP;+        sock_udp_send(&sock, &buf, 7, &gateway);+        return;+    }++    /* find the registered topic */+    for (sub = subs; sub && (sub->topic.id != tid); sub = sub->next) {}+    if (sub == NULL) {+        buf[6] = REJ_INVTID;+        sock_udp_send(&sock, &buf, 7, &gateway);+        DEBUG("[emcute] on pub: no subscription found\n");+    }+    else {+        if (rbuf[2] & EMCUTE_QOS_1) {+            sock_udp_send(&sock, &buf, 7, &gateway);+        }+        DEBUG("[emcute] on pub: got %i bytes of data\n", (int)(len - pos - 6));+        sub->cb(&sub->topic, &rbuf[pos + 6], (size_t)(len - pos - 6));+    }+}++static void on_pingreq(sock_udp_ep_t *remote)+{+    /* @todo    respond with a PINGRESP only if the PINGREQ came from the+     *          connected gateway -> see spec v1.2, section 6.11 */+    uint8_t buf[2] = { 2, PINGRESP };+    sock_udp_send(&sock, &buf, 2, remote);+}++static void on_pingresp(void)+{+    /** @todo: trigger update something like a 'last seen' value */+}++static void send_ping(void)+{+    if (gateway.port != 0) {+        uint8_t buf[2] = { 2, PINGREQ };+        sock_udp_send(&sock, &buf, 2, &gateway);+    }+}++int emcute_con(sock_udp_ep_t *remote, bool clean, const char *will_topic,+               const void *will_msg, size_t will_msg_len, unsigned will_flags)+{+    int res;+    size_t len;++    assert(!will_topic || (will_topic && will_msg && !(will_flags & ~PUB_FLAGS)));++    mutex_lock(&txlock);++    /* check for existing connections and copy given UDP endpoint */+    if (gateway.port != 0) {+        return EMCUTE_NOGW;+    }+    memcpy(&gateway, remote, sizeof(sock_udp_ep_t));++    /* figure out which flags to set */+    uint8_t flags = (clean) ? EMCUTE_CS : 0;+    if (will_topic) {+        flags |= EMCUTE_WILL;+    }++    /* compute packet size */+    len = (strlen(cli_id) + 6);+    tbuf[0] = (uint8_t)len;+    tbuf[1] = CONNECT;+    tbuf[2] = flags;+    tbuf[3] = PROTOCOL_VERSION;+    set_u16(&tbuf[4], EMCUTE_KEEPALIVE);+    memcpy(&tbuf[6], cli_id, strlen(cli_id));++    /* configure 'state machine' and send the connection request */+    if (will_topic) {+        size_t topic_len = strlen(will_topic);+        if ((topic_len > EMCUTE_TOPIC_MAXLEN) ||+            ((will_msg_len + 4) > EMCUTE_BUFSIZE)) {+            gateway.port = 0;+            return EMCUTE_OVERFLOW;+        }++        res = syncsend(WILLTOPICREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* now send WILLTOPIC */+        int pos = set_len(tbuf, (topic_len + 2));+        len = (pos + topic_len + 2);+        tbuf[pos++] = WILLTOPIC;+        tbuf[pos++] = will_flags;+        memcpy(&tbuf[pos], will_topic, strlen(will_topic));++        res = syncsend(WILLMSGREQ, len, false);+        if (res != EMCUTE_OK) {+            gateway.port = 0;+            return res;+        }++        /* and WILLMSG afterwards */+        pos = set_len(tbuf, (will_msg_len + 1));+        len = (pos + will_msg_len + 1);+        tbuf[pos++] = WILLMSG;+        memcpy(&tbuf[pos], will_msg, will_msg_len);+    }++    res = syncsend(CONNACK, len, true);+    if (res != EMCUTE_OK) {+        gateway.port = 0;+    }+    return res;+}++int emcute_discon(void)+{+    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = 2;+    tbuf[1] = DISCONNECT;++    return syncsend(DISCONNECT, 2, true);+}++int emcute_reg(emcute_topic_t *topic)+{+    assert(topic && topic->name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(topic->name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(topic->name) + 6);+    tbuf[1] = REGISTER;+    set_u16(&tbuf[2], 0);+    set_u16(&tbuf[4], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[6], topic->name, strlen(topic->name));++    int res = syncsend(REGACK, (size_t)tbuf[0], true);+    if (res > 0) {+        topic->id = (uint16_t)res;+        res = EMCUTE_OK;+    }+    return res;+}++int emcute_pub(emcute_topic_t *topic, const void *data, size_t len,+               unsigned flags)+{+    int res = EMCUTE_OK;++    assert((topic->id != 0) && data && (len > 0) && !(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len >= (EMCUTE_BUFSIZE - 9)) {+        return EMCUTE_OVERFLOW;+    }+    if (flags & EMCUTE_QOS_2) {+        return EMCUTE_NOTSUP;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 6));+    len += (pos + 6);+    tbuf[pos++] = PUBLISH;+    tbuf[pos++] = flags;+    set_u16(&tbuf[pos], topic->id);+    pos += 2;+    set_u16(&tbuf[pos], id_next);+    waitonid = id_next++;+    pos += 2;+    memcpy(&tbuf[pos], data, len);++    if (flags & EMCUTE_QOS_1) {+        res = syncsend(PUBACK, len, true);+    }+    else {+        sock_udp_send(&sock, tbuf, len, &gateway);+        mutex_unlock(&txlock);+    }++    return res;+}++int emcute_sub(emcute_sub_t *sub, unsigned flags)+{+    assert(sub && (sub->cb) && (sub->topic.name) && !(flags & ~SUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (strlen(sub->topic.name) > EMCUTE_TOPIC_MAXLEN) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = SUBSCRIBE;+    tbuf[2] = flags;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(SUBACK, (size_t)tbuf[0], false);+    if (res > 0) {+        DEBUG("[emcute] sub: success, topic id is %i\n", res);+        sub->topic.id = res;++        /* check if subscription is already in the list, only insert if not*/+        emcute_sub_t *s;+        for (s = subs; s && (s != sub); s = s->next) {}+        if (!s) {+            sub->next = subs;+            subs = sub;+            res = EMCUTE_OK;+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_unsub(emcute_sub_t *sub)+{+    assert(sub && sub->topic.name);++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }++    mutex_lock(&txlock);++    tbuf[0] = (strlen(sub->topic.name) + 5);+    tbuf[1] = UNSUBSCRIBE;+    tbuf[2] = 0;+    set_u16(&tbuf[3], id_next);+    waitonid = id_next++;+    memcpy(&tbuf[5], sub->topic.name, strlen(sub->topic.name));++    int res = syncsend(UNSUBACK, (size_t)tbuf[0], false);+    if (res == EMCUTE_OK) {+        if (subs == sub) {+            subs = sub->next;+        }+        else {+            emcute_sub_t *s;+            for (s = subs; s; s = s->next) {+                if (s->next == sub) {+                    s->next = sub->next;+                    break;+                }+            }+        }+    }++    mutex_unlock(&txlock);+    return res;+}++int emcute_willupd_topic(const char *topic, unsigned flags)+{+    assert(!(flags & ~PUB_FLAGS));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (topic && (strlen(topic) > EMCUTE_TOPIC_MAXLEN)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    tbuf[1] = WILLTOPICUPD;+    if (!topic) {+        tbuf[0] = 2;+    }+    else {+        tbuf[0] = (strlen(topic) + 3);+        tbuf[2] = flags;+        memcpy(&tbuf[3], topic, strlen(topic));+    }++    return syncsend(WILLTOPICRESP, (size_t)tbuf[0], true);+}++int emcute_willupd_msg(const void *data, size_t len)+{+    assert(data && (len > 0));++    if (gateway.port == 0) {+        return EMCUTE_NOGW;+    }+    if (len > (EMCUTE_BUFSIZE - 4)) {+        return EMCUTE_OVERFLOW;+    }++    mutex_lock(&txlock);++    int pos = set_len(tbuf, (len + 1));+    len += (pos + 1);

@haukepetersen This len += (pos + 1); looks suspicious. Coverity Scan tells us that there is a potential buffer overflow.

If you ask me, I would say that this statement should not there. And if it is intended then the if condition above needs to be changed.

haukepetersen

comment created time in 2 months

PullRequestReviewEvent

Pull request review commentRIOT-OS/RIOT

drivers/at86rf2xx: add smart idle listening feature

 void at86rf2xx_set_txpower(const at86rf2xx_t *dev, int16_t txpower) #endif } +int16_t at86rf2xx_get_rxsensitivity(const at86rf2xx_t *dev)+{+    uint8_t rxsens = at86rf2xx_reg_read(dev, AT86RF2XX_REG__RX_SYN)+                     & AT86RF2XX_RX_SYN__RX_PDT_LEVEL;+    return rx_sens_to_dbm[rxsens];+}++void at86rf2xx_set_rxsensitivity(const at86rf2xx_t *dev, int16_t rxsens)+{+    rxsens += MIN_RX_SENSITIVITY;++    if (rxsens < 0) {+        rxsens = 0;+    }+    else if (rxsens > MAX_RX_SENSITIVITY) {+        rxsens = MAX_RX_SENSITIVITY;+    }++    uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__RX_SYN);+    tmp &= ~(AT86RF2XX_RX_SYN__RX_PDT_LEVEL);+    tmp |= (dbm_to_rx_sens[rxsens] & AT86RF2XX_RX_SYN__RX_PDT_LEVEL);

@Hyungsin @PeterKietzmann First we should realize that MIN_RX_SENSITIVITY and MAX_RX_SENSITIVITY have negative values (roughly between -100 and -50).

If the incoming value of rxsense is greater than -MIN_RX_SENSITIVITY (say greater than 220), then it will get the value of MAX_RX_SENSITIVITY, which is a negative value.

If the incoming value of rxsense is smaller than -MIN_RX_SENSITIVITY, then it will get the value zero.

This looks suspicious, no?

Hyungsin

comment created time in 2 months

PullRequestReviewEvent

push eventkeestux/RIOT

Benjamin Valentin

commit sha 830bd34662f69f41b510aa68ac239dd28c19bd0e

pyterm: use Python3 in setup.py

view details

Benjamin Valentin

commit sha 12cf6f0137b00491342373e7273beb7abc43feff

buildsystem_sanity_check: use python3

view details

Thomas Stilwell

commit sha 651a3bf4233f88cae9249dabaddedea3a1621a57

cpu/efm32/timer: add support for LETIMER

view details

Thomas Stilwell

commit sha 37a6cc66f520d000fdb2d198fee857c51d6519db

cpu/efm32/timer: add pm blockers

view details

Thomas Stilwell

commit sha 754d790b3fa73b960dde97851eb1dcd68eb1ae7d

boards: efm32 boards: add support for LETIMER

view details

Benjamin Valentin

commit sha 48340f971fdd1e308747c7fceaee4661ea31c838

cpu/sam0_common: flashpage: clean up helper function

view details

Benjamin Valentin

commit sha 95ec5890b0fef801757f77054cd5a6aca9999774

cortexm_common: fix bit-banding check Not all MCUs ≥ Cortex-M3 provide the Bit-Banding feature. It is up to the manufacturer to implement it. Instead, rely on the CPU_HAS_BITBAND being set in `periph_cpu.h`.

view details

Benjamin Valentin

commit sha b716419462f2fa49c6cefcddcd375b3d4bbe482f

cpu/efm32: set CPU_HAS_BITBAND

view details

Benjamin Valentin

commit sha 8f36c88b93f8fd725579fcb7fc443fc2a1a0b158

cpu/stm32: set CPU_HAS_BITBAND

view details

Benjamin Valentin

commit sha f53ae74269346fc867de25c8584f157aa79d4a3d

cpu/kinetis: set CPU_HAS_BITBAND

view details

Marian Buschsieweke

commit sha a7cf50eb03d483a6395038bf6aa9006f86f9e3c9

drivers/stm32_eth: Code style fixes - Drop incorrect use of `volatile` - Fix missing spaces and indention

view details

Benjamin Valentin

commit sha 7269dc4e3accc3ed7927708017a3e3af5ec1b4af

cpu/sam0_common: i2c: allow arbitrary I2C frequencies The Atmel I2C peripheral supports arbitrary I2C frequencies. Since the `i2c_speed_t` enum just encodes the raw frequency values, we can just use them in the peripheral definition. We just have to remove the switch-case block that will generate an error for values outside of `i2c_speed_t`.

view details

Benjamin Valentin

commit sha 2fb0d9061f07b7d139e463e377b3f50c33ca1d7f

cpu/sam0_common: i2c: fix High Speed

view details

Benjamin Valentin

commit sha 4df36cbfda0f8b3afbb01bf1396241a759546792

cpu/sam0_common: i2c: improve readability of baud rate calculation Use variables to represent fSCL an fGCLK to make the baud rate calculation more readable.

view details

Marian Buschsieweke

commit sha a5dbec33d998cacb6fb76d48fccc72b1ab173818

cpu/stm32/periph_eth: Cleanup & fix DMA descriptor - Add missing `volatile` to DMA descriptor, as memory is also accessed by the DMA without knowledge of the compiler - Dropped `__attribute__((packed))` from DMA descriptor - The DMA descriptor fields need to be aligned on word boundries to properly function - The compiler can now more efficiently access the fields (safes ~300 B ROM) - Moved the DMA descriptor struct and the flags to `periph_cpu.h` - This allows Doxygen documentation being build for it - Those types and fields are needed for a future PTP implementation - Renamed DMA descriptor flags - They now reflect to which field in the DMA descriptor they refer to, so that confusion is avoided - Added documentation to the DMA descriptor and the corresponding flags

view details

Marian Buschsieweke

commit sha 53375f04bf79af72646462d0cf8cfc089fc24019

cpu/stm32/periph_eth: Optimize / fix flush - Added missing wait for TX flush - Grouped access to the same registers of the Ethernet PHY to reduce accesses. (The compiler won't optimize accesses to `volatile`, as defined in the C standard.)

view details

Benjamin Valentin

commit sha 9970c57cdf23ebcea94df4a63517813686078f5a

cpu/stm32: GPIO: use bitarithm_test_and_clear()

view details

Benjamin Valentin

commit sha cc2a3c9fd34cd11f6bb42f332924f993e3777d8d

cpu/sam0_common: GPIO: use bitarithm_test_and_clear()

view details

Juan Carrano

commit sha d167cb3af8885be2e6cdeb57f3cbf851f3a7e23e

sys/ps: Improve robustness against string table errors. The mapping from thread state codes to a human readable string in the PS modules has to be maintained manually. There is a very real possibility for it to get out of sync with the actual defined states, which would cause a crash when a lookup with an out of bounds index is performed. Also, because of the way the array is defined, there could be gaps (which will be filled by nulls). This patch replaces the array looukup by a function that checks bounds and also triggers an assertion so that the issue can be caught during development.

view details

Francisco Molina

commit sha 1a66ce3d23028a08730fd099c789adf53398303e

sys/ps/ps: use same order as tcb for lookup table

view details

push time in 2 months

issue commentRIOT-OS/RIOT

tests/cpp11_%: failing on i-nucleo-lrwan1

I see. However, % in makefiles is not equivalent to * wildcard (or glob).

In the title of this issue it makes more sense to use *, so I'll change it.

fjmolinas

comment created time in 2 months

issue openedRIOT-OS/RIOT

Return value of gnrc_netif_ipv6_addr_idx is not checked for negative

Description

The return value of gnrc_netif_ipv6_addr_idx is not always checked for negative values before it is used as an index in an array.

For example in nib.c

        int idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt);

        if (gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) {

BTW This is one of the findings of Coverity Scan. And I'm searching for a nice method to report findings like this. It may not always be that it is a real issue. Some can be obvious, some need discussion.

created time in 2 months

issue commentRIOT-OS/RIOT

tests/cpp11_%: failing on i-nucleo-lrwan1

@fjmolinas why do you use % in the title? Don't you mean *, which is common for "glob"?

fjmolinas

comment created time in 2 months

issue closedRIOT-OS/RIOT

tests/periph_timer_periodic is failing

Description

Test tests/periph_timer_periodic is failing on my SODAQ boards. These are the only boards I have so I can't tell if the test fails on other boards boards as well. My suspicion is that it fails on SAMD21.

Steps to reproduce the issue

Build and run tests/periph_timer_periodic

Expected results

The output should end with

TEST SUCCEEDED

Actual results

...
2020-06-07 21:08:53,834 # [0] tick
2020-06-07 21:08:53,838 # [1] tick
2020-06-07 21:08:53,869 # [0] tick
2020-06-07 21:08:53,869 # 
2020-06-07 21:08:53,869 # Cycles:
2020-06-07 21:08:53,870 # channel 0 = 12	[OK]
2020-06-07 21:08:53,870 # channel 1 = 11	[ERROR]
2020-06-07 21:08:53,871 # TEST FAILED

closed time in 2 months

keestux

issue commentRIOT-OS/RIOT

tests/periph_timer_periodic is failing

The test is passing. Closing

keestux

comment created time in 2 months

push eventkeestux/RIOT

Benjamin Valentin

commit sha 47deeab8422238e4126808d0f206df72a9ffce85

tests/periph_gpio: enable shell commands It is useful to have the `pm` command available in this test to see how GPIOs react to different sleep modes. Enable it be enabling the `shell_commands` module.

view details

hugues

commit sha 16e454ccaf5f6df2945befd3ba421087c6f682f8

cpu/stm32/periph/pwm: some bugfixes...

view details

hugues

commit sha a5da5953b257e22adfb712100544393b771ac50f

cpu/stm32/periph/pwm: multiple devices PWM_RIGHT mode bugfix

view details

hugues

commit sha d069c6e7873889666d2b331c06a1078ab0a64c1b

cpu/stm32/periph/pwm: CCMR1 was defined a second time instead of CCMR2

view details

hugues

commit sha 304d3f9e8d2accb5acec9de10fa948d46ec47088

cpu/stm32/periph/pwm: some bugfixes...

view details

Benjamin Valentin

commit sha 82dff2a2a3238267758aa3bf30960a1f8fe27f9a

tests/driver_pca9633: fix conflict with libc function name

view details

Benjamin Valentin

commit sha cde098f60e73f01353229c96d7841935f4d97765

tests/periph_gpio: fix conflict with libc function name

view details

Martine S. Lenders

commit sha 8dba9a918864afa31291c8e6dd2feb32f25a8f9f

netopt: remove deprecated alias NETOPT_LINK_CONNECTED

view details

Benjamin Valentin

commit sha b9ed7e9ffd949f16f0eb4335f2ebbeeaea100fcc

drivers/bme680: fix conflict with libc function name

view details

Benjamin Valentin

commit sha 5f4838e7160f7ca6d3a81409a3848627c8b72b40

drivers/sht3x: fix conflict with libc function name

view details

Benjamin Valentin

commit sha f4e9ede7bcd1a21848987acf0588b67e16ddb5d9

drivers/sps30: fix conflict with libc function name

view details

Alexandre Abadie

commit sha 1cf8f0dc4532bff26269c8d1f053070c6f777bc5

drivers/Makefile.dep: remove useless FEATURES_PROVIDED for rtc_rtt

view details

Alexandre Abadie

commit sha 988638715fae7b39af4a5c355185a0ddc257a401

cpu/nrf5x_common: remove inappropriate rtc dependency resolution

view details

hugues

commit sha 0926a04b08e8e1ab65e131dffd2fccd7d41440b9

cpu/stm32/periph/pwm: useless static var and a semicolon removed

view details

Jannes

commit sha 0c04de92ac55476db86e61b675cc7fa393dff573

sys/include/net: Add SOME/IP header

view details

Marian Buschsieweke

commit sha cf482c5d4673d3e09dce09f64f15eb14e856c04d

build system: Add libstdcpp feature and doc - Add libstdcpp feature to indicate a platform is providing a libstdc++ implementation ready for use - The existing cpp feature now only indicates a working C++ toolchain without libstdc++. (E.g. still useful for the Arduino compatibility layer.) - Added libstdcpp as required feature were needed - Added some documentation on C++ on RIOT

view details

Marian Buschsieweke

commit sha 0ed7ead587777ecb142143b57271473b9cc5e0b2

cpu/native: Workaround for libstdcpp for FreeBSD On FreeBSD, libstdc++ is known to not work with -m32. Thus, we don't provide it feature libstdcpp there.

view details

Jannes

commit sha 37cb65971f59e6f8214325f6c3c0220fa27ca24f

sys/include/net: Add suggested changes

view details

Alexandre Abadie

commit sha 67068393a97d838db4080065018bf63ba0c444e2

pkg/stm32cmsis: add package for STM32 cmsis device repositories

view details

Alexandre Abadie

commit sha 1f0a3a6baeea5bceaedced24b8f15b075c711d9b

cpu/cortexm_common: add special case for SVC interrupt configuration by default stm32f0/l0/l1 families simply call the interrupt enum SVC_IRQn

view details

push time in 3 months

Pull request review commentRIOT-OS/RIOT

gnrc_sixlowpan_frag_vrb: fix issues with interval marker inherited from base

 gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add(                                              vrbe->super.dst_len,                                              addr_str), vrbe->out_tag);             }+            /* _equal_index() => append intervals of `base`, so they don't get+             * lost. We use append, so we don't need to change base! */+            else if (base->ints != NULL) {+                gnrc_sixlowpan_frag_rb_int_t *tmp = vrbe->super.ints;++                if (tmp != base->ints) {+                    /* base->ints is not already vrbe->super.ints */+                    if (tmp != NULL) {+                        /* iterate before appending and check if `base->ints` is+                         * not already part of list */+                        while (tmp->next != NULL) {+                            if (tmp == base->ints) {+                                tmp = NULL;+                            }+                            /* cppcheck-suppress nullPointer

BTW Thanks to Coverity Scan

miri64

comment created time in 3 months

pull request commentRIOT-OS/RIOT

gnrc_ipv6_nib: fix border router with DNS & Context Compression

@miri64 's pointer arithmetic kung-fu was not so bad after all :-)

benpicco

comment created time in 3 months

pull request commentRIOT-OS/RIOT

gnrc/nib: fix _idx_dsts() calculation

So, we may conclude that Coverity Scan has benefits :-)

benpicco

comment created time in 3 months

Pull request review commentRIOT-OS/RIOT

gnrc_sixlowpan_frag_vrb: fix issues with interval marker inherited from base

 gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add(                                              vrbe->super.dst_len,                                              addr_str), vrbe->out_tag);             }+            /* _equal_index() => append intervals of `base`, so they don't get+             * lost. We use append, so we don't need to change base! */+            else if (base->ints != NULL) {+                gnrc_sixlowpan_frag_rb_int_t *tmp = vrbe->super.ints;++                if (tmp != base->ints) {+                    /* base->ints is not already vrbe->super.ints */+                    if (tmp != NULL) {+                        /* iterate before appending and check if `base->ints` is+                         * not already part of list */+                        while (tmp->next != NULL) {+                            if (tmp == base->ints) {+                                tmp = NULL;+                            }+                            /* cppcheck-suppress nullPointer

@miri64 Can you confirm, just for my sake, why this comment is correct?

tmp can't clearly be a NULL pointer here

If that statement is true then the if right above should never be taken.

Or did you perhaps forgot to add a break?

miri64

comment created time in 3 months

pull request commentRIOT-OS/RIOT

gnrc_ipv6_nib: fix border router with DNS & Context Compression

@benpicco @miri64 Objection!!

Commit a3adaa7 is wrong. The commit message:

We must divide the pointer difference (in bytes) by the size of the individual elements to get the index of the element.

That is not correct. In C when you subtract two pointers you don't get the pointer difference in bytes. (( Well, only if you subtract pointers to 1 byte objects. ))

#include <stdio.h>

typedef struct s1
{
    int mem1;
    char mem2;
} s1_t;

s1_t somearr[10];

int foo(s1_t* s)
{
    return s - somearr;
}

int main(int argc, char* argv[])
{
    printf("%d\n", foo(&somearr[3]));
    return 0;
}
gcc -Wall -o sub sub.c && ./sub
3

Or am I missing something obvious?

BTW. This is one of the discoveries of Coverity Scan.

benpicco

comment created time in 3 months

more