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