Um pequeno programa de teste para obter alguns campos de uma declaração.
[cascardo/libreceita.git] / rnet_message.c
1 /*
2  *  Copyright (C) 2013  Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
3  *  Copyright (C) 2014  Alexandre Oliva <lxoliva@fsfla.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #include "rnet_message.h"
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <netdb.h>
26
27 #ifndef MAX
28 #define MAX(a,b) (a >= b) ? a : b
29 #endif
30
31 int rnet_message_expand(struct rnet_message **message, size_t len)
32 {
33         struct rnet_message *msg = *message;
34         struct rnet_message *nmsg;
35         if (msg)
36                 len += msg->alen;
37         nmsg = realloc(msg, sizeof(*msg) + len);
38         if (!nmsg)
39                 return -1;
40         nmsg->alen = len;
41         if (!msg)
42                 nmsg->len = 0;
43         *message = nmsg;
44         return 0;
45 }
46
47 struct rnet_message * rnet_message_new(void)
48 {
49         struct rnet_message *msg = NULL;
50         int r;
51         r = rnet_message_expand(&msg, 1118);
52         if (r)
53                 return NULL;
54         return msg;
55 }
56
57 void rnet_message_del(struct rnet_message *message)
58 {
59         free(message);
60 }
61
62 int rnet_message_strip(struct rnet_message *message, size_t len)
63 {
64         if (len > message->len)
65                 return -1;
66         message->len -= len;
67         memmove(message->buffer, message->buffer + len, message->len);
68         return 0;
69 }
70
71 static int add_field(struct rnet_message **message, char *key, int klen,
72                                                 char *val, int vlen)
73 {
74         int n = 0;
75         char *buffer;
76         struct rnet_message *msg = *message;
77         if ((msg->alen - msg->len) < (size_t) (klen + vlen + 3)) {
78                 if (rnet_message_expand(message, MAX(msg->len, (size_t) (klen + vlen + 3))))
79                         return -ENOMEM;
80                 msg = *message;
81         }
82         buffer = msg->buffer + msg->len;
83         if (klen > 0x7f || klen < 0)
84                 return -EINVAL;
85         if (vlen > 0x7fff || vlen < 0)
86                 return -EINVAL;
87         buffer[0] = klen & 0x7f;
88         if (vlen > 0x7f)
89                 buffer[0] |= 0x80;
90         buffer++;
91         n++;
92         memcpy(buffer, key, klen);
93         buffer += klen;
94         n += klen;
95         if (vlen > 0x7f) {
96                 buffer[0] = (vlen >> 8) & 0x7f;
97                 buffer[1] = vlen & 0xff;
98                 buffer += 2;
99                 n += 2;
100         } else {
101                 buffer[0] = vlen & 0x7f;
102                 buffer++;
103                 n++;
104         }
105         memcpy(buffer, val, vlen);
106         n += vlen;
107         msg->len += n;
108         return n;
109 }
110
111 int rnet_message_add_u32(struct rnet_message **msg, char *key, uint32_t val)
112 {
113         uint32_t nval = htonl(val);
114         return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val));
115 }
116
117 int rnet_message_add_ascii(struct rnet_message **msg, char *key, char *val)
118 {
119         return add_field(msg, key, strlen(key), val, strlen(val));
120 }
121
122 int rnet_message_add_u8(struct rnet_message **msg, char *key, uint8_t val)
123 {
124         return add_field(msg, key, strlen(key), (char *) &val, sizeof(val));
125 }
126
127 int rnet_message_add_u16(struct rnet_message **msg, char *key, uint16_t val)
128 {
129         uint16_t nval = htons(val);
130         return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val));
131 }
132
133 int rnet_message_add_u64(struct rnet_message **msg, char *key, uint64_t val)
134 {
135         uint64_t nval = htobe64(val);
136         return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val));
137 }
138
139 int rnet_message_add_buffer(struct rnet_message **msg, char *key,
140                                 char *buffer, size_t len)
141 {
142         return add_field(msg, key, strlen(key), buffer, len);
143 }
144
145 int rnet_message_parse(struct rnet_message *msg, char *skey,
146                                 char** value, int *vlen)
147 {
148         char * buffer = msg->buffer;
149         size_t len = msg->len;
150         unsigned int i = 0;
151         unsigned int j;
152         int b;
153         char *key;
154         unsigned int klen;
155         /* skip first byte */
156         i++;
157         while (i < len) {
158                 j = (unsigned char)buffer[i];
159                 b = j & 0x80;
160                 j = j & 0x7f;
161                 i++;
162                 key = buffer + i;
163                 klen = j;
164                 i += j;
165                 j = (unsigned char)buffer[i];
166                 i++;
167                 if (b)
168                         j = j << 8 | (unsigned char)buffer[i++];
169                 *value = buffer + i;
170                 *vlen = j;
171                 i += j;
172                 if (strlen(skey) == klen && !strncasecmp(key, skey, klen))
173                         return 0;
174         }
175         return 1;
176 }