GNUnet  0.11.x
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"
29 #include "gnunet-service-core.h"
32 #include <zlib.h>
33 
34 
40 {
41  uint32_t bits[(UINT16_MAX + 1) / 32];
42 };
43 
47 static struct GSC_TypeMap my_type_map;
48 
52 static uint8_t map_counters[UINT16_MAX + 1];
53 
58 static struct GNUNET_HashCode my_tm_hash;
59 
63 static int hash_current;
64 
65 
69 static void
71 {
73 }
74 
75 
82 void
83 GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
84 {
85  GNUNET_CRYPTO_hash (tm, sizeof(struct GSC_TypeMap), hc);
86 }
87 
88 
95 int
97 {
98  if (GNUNET_NO == hash_current)
99  {
102  }
103  return (0 == memcmp (hc, &my_tm_hash, sizeof(struct GNUNET_HashCode)))
104  ? GNUNET_YES
105  : GNUNET_NO;
106 }
107 
108 
114 struct GNUNET_MessageHeader *
116 {
117  char *tmp;
118  uLongf dlen;
119  struct GNUNET_MessageHeader *hdr;
120 
121 #ifdef compressBound
122  dlen = compressBound (sizeof(my_type_map));
123 #else
124  dlen = sizeof(my_type_map) + (sizeof(my_type_map) / 100) + 20;
125  /* documentation says 100.1% oldSize + 12 bytes, but we
126  * should be able to overshoot by more to be safe */
127 #endif
128  hdr = GNUNET_malloc (dlen + sizeof(struct GNUNET_MessageHeader));
129  tmp = (char *) &hdr[1];
130  if ((Z_OK != compress2 ((Bytef *) tmp,
131  &dlen,
132  (const Bytef *) &my_type_map,
133  sizeof(my_type_map),
134  9)) ||
135  (dlen >= sizeof(my_type_map)))
136  {
137  /* compression failed, use uncompressed map */
138  dlen = sizeof(my_type_map);
139  GNUNET_memcpy (tmp, &my_type_map, sizeof(my_type_map));
141  }
142  else
143  {
144  /* compression worked, use compressed map */
146  }
147  hdr->size = htons ((uint16_t) dlen + sizeof(struct GNUNET_MessageHeader));
148  return hdr;
149 }
150 
151 
158 struct GSC_TypeMap *
160 {
161  struct GSC_TypeMap *ret;
162  uint16_t size;
163  uLongf dlen;
164 
165  size = ntohs (msg->size);
166  switch (ntohs (msg->type))
167  {
170  gettext_noop ("# type maps received"),
171  1,
172  GNUNET_NO);
173  if (size != sizeof(struct GSC_TypeMap))
174  {
175  GNUNET_break_op (0);
176  return NULL;
177  }
178  ret = GNUNET_new (struct GSC_TypeMap);
179  GNUNET_memcpy (ret, &msg[1], sizeof(struct GSC_TypeMap));
180  return ret;
181 
184  gettext_noop ("# type maps received"),
185  1,
186  GNUNET_NO);
187  ret = GNUNET_new (struct GSC_TypeMap);
188  dlen = sizeof(struct GSC_TypeMap);
189  if ((Z_OK != uncompress ((Bytef *) ret,
190  &dlen,
191  (const Bytef *) &msg[1],
192  (uLong) size)) ||
193  (dlen != sizeof(struct GSC_TypeMap)))
194  {
195  GNUNET_break_op (0);
196  GNUNET_free (ret);
197  return NULL;
198  }
199  return ret;
200 
201  default:
202  GNUNET_break (0);
203  return NULL;
204  }
205 }
206 
207 
211 static void
213 {
214  struct GNUNET_MessageHeader *hdr;
215 
218  gettext_noop ("# updates to my type map"),
219  1,
220  GNUNET_NO);
222  GNUNET_free (hdr);
223 }
224 
225 
232 void
233 GSC_TYPEMAP_add (const uint16_t *types, unsigned int tlen)
234 {
235  unsigned int i;
236  int changed;
237 
238  changed = GNUNET_NO;
239  for (i = 0; i < tlen; i++)
240  {
241  if (0 == map_counters[types[i]]++)
242  {
243  my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32));
244  changed = GNUNET_YES;
245  }
246  }
247  if (GNUNET_YES == changed)
248  {
249  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Typemap changed, broadcasting!\n");
250  rehash_typemap ();
252  }
253 }
254 
255 
262 void
263 GSC_TYPEMAP_remove (const uint16_t *types, unsigned int tlen)
264 {
265  int changed;
266 
267  changed = GNUNET_NO;
268  for (unsigned int i = 0; i < tlen; i++)
269  {
270  if (0 == --map_counters[types[i]])
271  {
272  my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
273  changed = GNUNET_YES;
274  }
275  }
276  if (GNUNET_YES == changed)
277  {
278  rehash_typemap ();
280  }
281 }
282 
283 
293 int
295  const uint16_t *types,
296  unsigned int tcnt)
297 {
298  if (NULL == tmap)
299  return GNUNET_NO;
300  if (0 == tcnt)
301  return GNUNET_YES; /* matches all */
302  for (unsigned int i = 0; i < tcnt; i++)
303  if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
304  return GNUNET_YES;
305  return GNUNET_NO;
306 }
307 
308 
317 struct GSC_TypeMap *
318 GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
319  const uint16_t *types,
320  unsigned int tcnt)
321 {
322  struct GSC_TypeMap *ret;
323 
324  ret = GNUNET_new (struct GSC_TypeMap);
325  if (NULL != tmap)
326  GNUNET_memcpy (ret, tmap, sizeof(struct GSC_TypeMap));
327  for (unsigned int i = 0; i < tcnt; i++)
328  ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
329  return ret;
330 }
331 
332 
338 struct GSC_TypeMap *
340 {
341  return GNUNET_new (struct GSC_TypeMap);
342 }
343 
344 
350 void
352 {
353  GNUNET_free (tmap);
354 }
355 
356 
360 void
362 {
363  /* nothing to do */
364 }
365 
366 
370 void
372 {
373  /* nothing to do */
374 }
375 
376 
377 /* end of gnunet-service-core_typemap.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define gettext_noop(String)
Definition: gettext.h:69
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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.
struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message()
Compute a type map message for this peer.
static struct GNUNET_HashCode my_tm_hash
Current hash of our (uncompressed) type map.
void GSC_TYPEMAP_done()
Shutdown typemap subsystem.
void GSC_TYPEMAP_destroy(struct GSC_TypeMap *tmap)
Free the given 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.
struct GSC_TypeMap * GSC_TYPEMAP_create()
Create an empty 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.
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_check_hash(const struct GNUNET_HashCode *hc)
Check if the given hash matches our current type map.
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.
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 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
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
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
#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:67
A 512-bit hashcode.
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
A type map describing which messages a given neighbour is able to process.
uint32_t bits[(UINT16_MAX+1)/32]