diff options
author | Michael Scott <michael.scott@linaro.org> | 2017-01-23 15:24:42 -0800 |
---|---|---|
committer | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2017-02-03 15:59:16 +0200 |
commit | 103c1aff9b989eeca78f913b29439f4af975311a (patch) | |
tree | b6528eec09482fed91f3819a887fee9db174a495 /samples | |
parent | 50a93d906d248b847f8436923644a602d0b99b5c (diff) |
samples: net: irc_bot: handle messages across multiple fragments
Often IRC messages are split across multiple netbuf fragments.
Let's fix the message processing to account for this.
Change-Id: I3835af6adf337d27c28a0beeb72848dcc838772c
Signed-off-by: Michael Scott <michael.scott@linaro.org>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/net/irc_bot/src/irc-bot.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/samples/net/irc_bot/src/irc-bot.c b/samples/net/irc_bot/src/irc-bot.c index e92b6aa84..5c8c99d2a 100644 --- a/samples/net/irc_bot/src/irc-bot.c +++ b/samples/net/irc_bot/src/irc-bot.c @@ -33,6 +33,9 @@ #define STACK_SIZE 2048 uint8_t stack[STACK_SIZE]; +#define CMD_BUFFER_SIZE 256 +static uint8_t cmd_buf[CMD_BUFFER_SIZE]; + /* LED */ #if defined(LED0_GPIO_PORT) #define LED_GPIO_NAME LED0_GPIO_PORT @@ -232,6 +235,9 @@ on_context_recv(struct net_context *ctx, struct net_buf *buf, { struct zirc *irc = data; struct net_buf *tmp; + uint8_t *end_of_line; + size_t len; + uint16_t pos = 0, cmd_len = 0; if (!buf) { /* TODO: notify of disconnection, maybe reconnect? */ @@ -242,38 +248,49 @@ on_context_recv(struct net_context *ctx, struct net_buf *buf, if (status) { /* TODO: handle connection error */ NET_ERR("Connection error: %d\n", -status); + net_buf_unref(buf); return; } /* tmp points to fragment containing IP header */ tmp = buf->frags; - /* Adavance tmp fragment to appdata (TCP payload) */ - net_buf_pull(tmp, net_nbuf_appdata(buf) - tmp->data); + /* skip pos to the first TCP payload */ + pos = net_nbuf_appdata(buf) - tmp->data; while (tmp) { - while (true) { - char *end_of_line = memchr(tmp->data, '\r', - tmp->len); - size_t cmd_len; - - if (!end_of_line) { - break; - } + len = tmp->len - pos; - *end_of_line = '\0'; - cmd_len = end_of_line - (char *)tmp->data - 1; - process_command(irc, tmp->data, cmd_len); + end_of_line = memchr(tmp->data + pos, '\r', len); + if (end_of_line) { + len = end_of_line - (tmp->data + pos); + } - cmd_len++; /* Account for \n also */ - tmp->len -= cmd_len; - tmp->data += cmd_len; + if (cmd_len + len > sizeof(cmd_buf)) { + /* overrun cmd_buf - bail out */ + NET_ERR("CMD BUFFER OVERRUN!! %lu > %lu", + cmd_len + len, + sizeof(cmd_buf)); + break; } - net_buf_frag_del(buf, tmp); - tmp = buf->frags; + tmp = net_nbuf_read(tmp, pos, &pos, len, cmd_buf + cmd_len); + cmd_len += len; - /* TODO: handle messages that spans multiple fragments */ + if (end_of_line) { + /* skip the /n char after /r */ + if (tmp) { + tmp = net_nbuf_read(tmp, pos, &pos, 1, NULL); + } + + cmd_buf[cmd_len] = '\0'; + process_command(irc, cmd_buf, cmd_len); + cmd_len = 0; + } } + + net_buf_unref(buf); + + /* TODO: handle messages that spans multiple packets? */ } static int |