GNUnet 0.22.1
gnunet-service-core_typemap.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet-service-core.h"
31#include <zlib.h>
32
33
39{
40 uint32_t bits[(UINT16_MAX + 1) / 32];
41};
42
47
51static uint8_t map_counters[UINT16_MAX + 1];
52
58
62static int hash_current;
63
64
68static void
70{
72}
73
74
81void
82GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
83{
84 GNUNET_CRYPTO_hash (tm, sizeof(struct GSC_TypeMap), hc);
85}
86
87
94int
96{
98 {
101 }
102 return (0 == memcmp (hc, &my_tm_hash, sizeof(struct GNUNET_HashCode)))
103 ? GNUNET_YES
104 : GNUNET_NO;
105}
106
107
115{
116 char *tmp;
117 uLongf dlen;
118 struct GNUNET_MessageHeader *hdr;
119
120#ifdef compressBound
121 dlen = compressBound (sizeof(my_type_map));
122#else
123 dlen = sizeof(my_type_map) + (sizeof(my_type_map) / 100) + 20;
124 /* documentation says 100.1% oldSize + 12 bytes, but we
125 * should be able to overshoot by more to be safe */
126#endif
127 hdr = GNUNET_malloc (dlen + sizeof(struct GNUNET_MessageHeader));
128 tmp = (char *) &hdr[1];
129 if ((Z_OK != compress2 ((Bytef *) tmp,
130 &dlen,
131 (const Bytef *) &my_type_map,
132 sizeof(my_type_map),
133 9)) ||
134 (dlen >= sizeof(my_type_map)))
135 {
136 /* compression failed, use uncompressed map */
137 dlen = sizeof(my_type_map);
138 GNUNET_memcpy (tmp, &my_type_map, sizeof(my_type_map));
140 }
141 else
142 {
143 /* compression worked, use compressed map */
145 }
146 hdr->size = htons ((uint16_t) dlen + sizeof(struct GNUNET_MessageHeader));
147 return hdr;
148}
149
150
157struct GSC_TypeMap *
159{
160 struct GSC_TypeMap *ret;
161 uint16_t size;
162 uLongf dlen;
163
164 size = ntohs (msg->size);
165 switch (ntohs (msg->type))
166 {
169 gettext_noop ("# type maps received"),
170 1,
171 GNUNET_NO);
172 if (size != sizeof(struct GSC_TypeMap))
173 {
174 GNUNET_break_op (0);
175 return NULL;
176 }
177 ret = GNUNET_new (struct GSC_TypeMap);
178 GNUNET_memcpy (ret, &msg[1], sizeof(struct GSC_TypeMap));
179 return ret;
180
183 gettext_noop ("# type maps received"),
184 1,
185 GNUNET_NO);
186 ret = GNUNET_new (struct GSC_TypeMap);
187 dlen = sizeof(struct GSC_TypeMap);
188 if ((Z_OK != uncompress ((Bytef *) ret,
189 &dlen,
190 (const Bytef *) &msg[1],
191 (uLong) size)) ||
192 (dlen != sizeof(struct GSC_TypeMap)))
193 {
194 GNUNET_break_op (0);
196 return NULL;
197 }
198 return ret;
199
200 default:
201 GNUNET_break (0);
202 return NULL;
203 }
204}
205
206
210static void
212{
213 struct GNUNET_MessageHeader *hdr;
214
217 gettext_noop ("# updates to my type map"),
218 1,
219 GNUNET_NO);
221 GNUNET_free (hdr);
222}
223
224
231void
232GSC_TYPEMAP_add (const uint16_t *types, unsigned int tlen)
233{
234 unsigned int i;
235 int changed;
236
237 changed = GNUNET_NO;
238 for (i = 0; i < tlen; i++)
239 {
240 if (0 == map_counters[types[i]]++)
241 {
242 my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32));
243 changed = GNUNET_YES;
244 }
245 }
246 if (GNUNET_YES == changed)
247 {
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Typemap changed, broadcasting!\n");
251 }
252}
253
254
255void
256GSC_TYPEMAP_remove (const uint16_t *types, unsigned int tlen)
257{
258 int changed;
259
260 changed = GNUNET_NO;
261 for (unsigned int i = 0; i < tlen; i++)
262 {
263 if (0 == --map_counters[types[i]])
264 {
265 my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
266 changed = GNUNET_YES;
267 }
268 }
269 if (GNUNET_YES == changed)
270 {
273 }
274}
275
276
286int
288 const uint16_t *types,
289 unsigned int tcnt)
290{
291 if (NULL == tmap)
292 return GNUNET_NO;
293 if (0 == tcnt)
294 return GNUNET_YES; /* matches all */
295 for (unsigned int i = 0; i < tcnt; i++)
296 if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
297 return GNUNET_YES;
298 return GNUNET_NO;
299}
300
301
310struct GSC_TypeMap *
311GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
312 const uint16_t *types,
313 unsigned int tcnt)
314{
315 struct GSC_TypeMap *ret;
316
317 ret = GNUNET_new (struct GSC_TypeMap);
318 if (NULL != tmap)
319 GNUNET_memcpy (ret, tmap, sizeof(struct GSC_TypeMap));
320 for (unsigned int i = 0; i < tcnt; i++)
321 ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
322 return ret;
323}
324
325
331struct GSC_TypeMap *
333{
334 return GNUNET_new (struct GSC_TypeMap);
335}
336
337
343void
345{
346 GNUNET_free (tmap);
347}
348
349
353void
355{
356 /* nothing to do */
357}
358
359
363void
365{
366 /* nothing to do */
367}
368
369
370/* end of gnunet-service-core_typemap.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define gettext_noop(String)
Definition: gettext.h:74
static int ret
Final status code.
Definition: gnunet-arm.c:93
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
Globals for gnunet-service-core.
void GSC_SESSIONS_broadcast_typemap(const struct GNUNET_MessageHeader *msg)
Broadcast an updated typemap message to all neighbours.
static struct GNUNET_HashCode my_tm_hash
Current hash of our (uncompressed) type map.
struct GSC_TypeMap * GSC_TYPEMAP_extend(const struct GSC_TypeMap *tmap, const uint16_t *types, unsigned int tcnt)
Add additional types to a given typemap.
void GSC_TYPEMAP_done()
Shutdown typemap subsystem.
void GSC_TYPEMAP_destroy(struct GSC_TypeMap *tmap)
Free the given type map.
static void rehash_typemap()
Our type map changed, recompute its hash.
static struct GSC_TypeMap my_type_map
Bitmap of message types this peer is able to handle.
int GSC_TYPEMAP_check_hash(const struct GNUNET_HashCode *hc)
Check if the given hash matches our current type map.
struct GSC_TypeMap * GSC_TYPEMAP_create()
Create an empty type map.
struct GSC_TypeMap * GSC_TYPEMAP_get_from_message(const struct GNUNET_MessageHeader *msg)
Extract a type map from a TYPE_MAP message.
int GSC_TYPEMAP_test_match(const struct GSC_TypeMap *tmap, const uint16_t *types, unsigned int tcnt)
Test if any of the types from the types array is in the given type map.
static uint8_t map_counters[UINT16_MAX+1]
Counters for message types this peer is able to handle.
struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message()
Compute a type map message for this peer.
void GSC_TYPEMAP_add(const uint16_t *types, unsigned int tlen)
Add a set of types to our type map.
void GSC_TYPEMAP_hash(const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
Hash the contents of a type map.
void GSC_TYPEMAP_init()
Initialize typemap subsystem.
static int hash_current
Is my_tm_hash() current with respect to our type map?
void GSC_TYPEMAP_remove(const uint16_t *types, unsigned int tlen)
Remove a set of message types from our type map.
static void broadcast_my_type_map()
Send my type map to all connected peers (it got changed).
management of map that specifies which message types this peer supports
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP
uncompressed type map of the sender
#define GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP
gzip-compressed type map of the sender
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static unsigned int size
Size of the "table".
Definition: peer.c:68
A 512-bit hashcode.
Header for all communications.
A type map describing which messages a given neighbour is able to process.
uint32_t bits[(UINT16_MAX+1)/32]