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 
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
struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message()
Compute a type map message for this peer.
static uint8_t map_counters[UINT16_MAX+1]
Counters for message types this peer is able to handle.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static struct GSC_TypeMap my_type_map
Bitmap of message types this peer is able to handle.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
static int hash_current
Is my_tm_hash() current with respect to our type map?
#define GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP
gzip-compressed type map of the sender
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
management of map that specifies which message types this peer supports
static struct GNUNET_HashCode my_tm_hash
Current hash of our (uncompressed) type map.
uint32_t bits[(UINT16_MAX+1)/32]
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
static void rehash_typemap()
Our type map changed, recompute its hash.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
void GSC_TYPEMAP_destroy(struct GSC_TypeMap *tmap)
Free the given type map.
A 512-bit hashcode.
Globals for gnunet-service-core.
void GSC_TYPEMAP_init()
Initialize typemap subsystem.
struct GSC_TypeMap * GSC_TYPEMAP_create()
Create an empty type map.
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP
uncompressed type map of the sender
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.
void GSC_TYPEMAP_done()
Shutdown typemap subsystem.
void GSC_TYPEMAP_hash(const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
Hash the contents of a 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.
#define GNUNET_log(kind,...)
A type map describing which messages a given neighbour is able to process.
void GSC_TYPEMAP_remove(const uint16_t *types, unsigned int tlen)
Remove a set of types from our type map.
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GSC_SESSIONS_broadcast_typemap(const struct GNUNET_MessageHeader *msg)
Broadcast an updated typemap message to all neighbours.
static void broadcast_my_type_map()
Send my type map to all connected peers (it got changed).
struct GSC_TypeMap * GSC_TYPEMAP_get_from_message(const struct GNUNET_MessageHeader *msg)
Extract a type map from a TYPE_MAP message.
#define GNUNET_malloc(size)
Wrapper around malloc.
void GSC_TYPEMAP_add(const uint16_t *types, unsigned int tlen)
Add a set of types to our type map.
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69