GNUnet  0.10.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 
39 struct GSC_TypeMap {
40  uint32_t bits[(UINT16_MAX + 1) / 32];
41 };
42 
46 static struct GSC_TypeMap my_type_map;
47 
51 static uint8_t map_counters[UINT16_MAX + 1];
52 
58 
62 static int hash_current;
63 
64 
68 static void
70 {
72 }
73 
74 
81 void
82 GSC_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 
94 int
96 {
97  if (GNUNET_NO == hash_current)
98  {
101  }
102  return (0 == memcmp(hc, &my_tm_hash, sizeof(struct GNUNET_HashCode)))
103  ? GNUNET_YES
104  : GNUNET_NO;
105 }
106 
107 
113 struct GNUNET_MessageHeader *
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 
157 struct 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);
195  GNUNET_free(ret);
196  return NULL;
197  }
198  return ret;
199 
200  default:
201  GNUNET_break(0);
202  return NULL;
203  }
204 }
205 
206 
210 static 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 
231 void
232 GSC_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");
249  rehash_typemap();
251  }
252 }
253 
254 
261 void
262 GSC_TYPEMAP_remove(const uint16_t *types, unsigned int tlen)
263 {
264  int changed;
265 
266  changed = GNUNET_NO;
267  for (unsigned int i = 0; i < tlen; i++)
268  {
269  if (0 == --map_counters[types[i]])
270  {
271  my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
272  changed = GNUNET_YES;
273  }
274  }
275  if (GNUNET_YES == changed)
276  {
277  rehash_typemap();
279  }
280 }
281 
282 
292 int
294  const uint16_t *types,
295  unsigned int tcnt)
296 {
297  if (NULL == tmap)
298  return GNUNET_NO;
299  if (0 == tcnt)
300  return GNUNET_YES; /* matches all */
301  for (unsigned int i = 0; i < tcnt; i++)
302  if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
303  return GNUNET_YES;
304  return GNUNET_NO;
305 }
306 
307 
316 struct GSC_TypeMap *
317 GSC_TYPEMAP_extend(const struct GSC_TypeMap *tmap,
318  const uint16_t *types,
319  unsigned int tcnt)
320 {
321  struct GSC_TypeMap *ret;
322 
323  ret = GNUNET_new(struct GSC_TypeMap);
324  if (NULL != tmap)
325  GNUNET_memcpy(ret, tmap, sizeof(struct GSC_TypeMap));
326  for (unsigned int i = 0; i < tcnt; i++)
327  ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
328  return ret;
329 }
330 
331 
337 struct GSC_TypeMap *
339 {
340  return GNUNET_new(struct GSC_TypeMap);
341 }
342 
343 
349 void
351 {
352  GNUNET_free(tmap);
353 }
354 
355 
359 void
361 {
362  /* nothing to do */
363 }
364 
365 
369 void
371 {
372  /* nothing to do */
373 }
374 
375 /* 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.
#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 ret
Final status code.
Definition: gnunet-arm.c:89
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:44
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:66
#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