From 1572742121525f14d243de4b29bab373fa667ddf Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 11 Jun 2013 18:21:50 -0300 Subject: [PATCH] Create rnet_message to encode messages. rnet_message allows us to encode messages in the form used for ReceitaNet, which is a kind of set of key/values. --- rnet_message.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ rnet_message.h | 36 +++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 rnet_message.c create mode 100644 rnet_message.h diff --git a/rnet_message.c b/rnet_message.c new file mode 100644 index 0000000..cd7cfa0 --- /dev/null +++ b/rnet_message.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 Thadeu Lima de Souza Cascardo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "rnet_message.h" +#include +#include +#include +#include +#include + +#ifndef MAX +#define MAX(a,b) (a >= b) ? a : b +#endif + +static int rnet_message_expand(struct rnet_message **message, size_t len) +{ + struct rnet_message *msg = *message; + struct rnet_message *nmsg; + if (msg) + len += msg->alen; + nmsg = realloc(msg, sizeof(*msg) + len); + if (!nmsg) + return -1; + nmsg->alen = len; + if (!msg) + nmsg->len = 0; + *message = nmsg; + return 0; +} + +struct rnet_message * rnet_message_new(void) +{ + struct rnet_message *msg = NULL; + int r; + r = rnet_message_expand(&msg, 1118); + if (r) + return NULL; + return msg; +} + +void rnet_message_del(struct rnet_message *message) +{ + free(message); +} + +static int add_field(struct rnet_message *msg, char *key, int klen, char *val, int vlen) +{ + int n = 0; + char *buffer; + if ((msg->alen - msg->len) < (klen + vlen + 3)) { + if (rnet_message_expand(&msg, MAX(msg->len, klen + vlen + 3))) + return -ENOMEM; + } + buffer = msg->buffer + msg->len; + if (klen > 0x7f || klen < 0) + return -EINVAL; + if (vlen > 0x7fff || vlen < 0) + return -EINVAL; + buffer[0] = klen & 0x7f; + if (vlen > 0x7f) + buffer[0] |= 0x80; + buffer++; + n++; + memcpy(buffer, key, klen); + buffer += klen; + n += klen; + if (vlen > 0x7f) { + buffer[0] = (vlen >> 8) & 0x7f; + buffer[1] = vlen & 0xff; + buffer += 2; + n += 2; + } else { + buffer[0] = vlen & 0x7f; + buffer++; + n++; + } + memcpy(buffer, val, vlen); + n += vlen; + msg->len += n; + return n; +} + +int rnet_message_add_u32(struct rnet_message *msg, char *key, uint32_t val) +{ + uint32_t nval = htonl(val); + return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val)); +} + +int rnet_message_add_ascii(struct rnet_message *msg, char *key, char *val) +{ + return add_field(msg, key, strlen(key), val, strlen(val)); +} diff --git a/rnet_message.h b/rnet_message.h new file mode 100644 index 0000000..8348987 --- /dev/null +++ b/rnet_message.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 Thadeu Lima de Souza Cascardo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _RNET_MESSAGE_H +#define _RNET_MESSAGE_H + +#include + +struct rnet_message { + int len; + int alen; + char buffer[]; +}; + +struct rnet_message * rnet_message_new(void); +void rnet_message_del(struct rnet_message *message); + +int rnet_message_add_u32(struct rnet_message *msg, char *key, uint32_t val); +int rnet_message_add_ascii(struct rnet_message *msg, char *key, char *val); + +#endif -- 2.20.1