2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file core/gnunet-service-core_typemap.c
23 * @brief management of map that specifies which message types this peer supports
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_transport_service.h"
29 #include "gnunet-service-core.h"
30 #include "gnunet-service-core_sessions.h"
31 #include "gnunet-service-core_typemap.h"
36 * A type map describing which messages a given neighbour is able
41 uint32_t bits[(UINT16_MAX + 1) / 32];
45 * Bitmap of message types this peer is able to handle.
47 static struct GSC_TypeMap my_type_map;
50 * Counters for message types this peer is able to handle.
52 static uint8_t map_counters[UINT16_MAX + 1];
56 * Compute a type map message for this peer.
58 * @return this peers current type map message.
60 struct GNUNET_MessageHeader *
61 GSC_TYPEMAP_compute_type_map_message ()
65 struct GNUNET_MessageHeader *hdr;
68 dlen = compressBound (sizeof (my_type_map));
70 dlen = sizeof (my_type_map) + (sizeof (my_type_map) / 100) + 20;
71 /* documentation says 100.1% oldSize + 12 bytes, but we
72 * should be able to overshoot by more to be safe */
74 hdr = GNUNET_malloc (dlen + sizeof (struct GNUNET_MessageHeader));
75 tmp = (char *) &hdr[1];
77 compress2 ((Bytef *) tmp, &dlen, (const Bytef *) &my_type_map,
78 sizeof (my_type_map), 9)) || (dlen >= sizeof (my_type_map)))
80 dlen = sizeof (my_type_map);
81 memcpy (tmp, &my_type_map, sizeof (my_type_map));
82 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP);
86 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP);
88 hdr->size = htons ((uint16_t) dlen + sizeof (struct GNUNET_MessageHeader));
94 * Extract a type map from a TYPE_MAP message.
96 * @param msg a type map message
97 * @return NULL on error
100 GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg)
102 struct GSC_TypeMap *ret;
106 size = ntohs (msg->size);
107 switch (ntohs (msg->type))
109 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
110 GNUNET_STATISTICS_update (GSC_stats,
111 gettext_noop ("# type maps received"),
114 if (size != sizeof (struct GSC_TypeMap))
119 ret = GNUNET_malloc (sizeof (struct GSC_TypeMap));
120 memcpy (ret, &msg[1], sizeof (struct GSC_TypeMap));
122 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
123 GNUNET_STATISTICS_update (GSC_stats,
124 gettext_noop ("# type maps received"),
127 ret = GNUNET_malloc (sizeof (struct GSC_TypeMap));
128 dlen = sizeof (struct GSC_TypeMap);
130 uncompress ((Bytef*) ret, &dlen,
131 (const Bytef*) &msg[1], (uLong) size)) ||
132 (dlen != sizeof (struct GSC_TypeMap) ) )
147 * Send my type map to all connected peers (it got changed).
150 broadcast_my_type_map ()
152 struct GNUNET_MessageHeader *hdr;
154 hdr = GSC_TYPEMAP_compute_type_map_message ();
155 GNUNET_STATISTICS_update (GSC_stats,
156 gettext_noop ("# updates to my type map"),
159 GSC_SESSIONS_broadcast (hdr);
165 * Add a set of types to our type map.
168 GSC_TYPEMAP_add (const uint16_t *types,
177 if (0 == map_counters[types[i]]++)
179 my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32));
180 changed = GNUNET_YES;
183 if (GNUNET_YES == changed)
184 broadcast_my_type_map ();
189 * Remove a set of types from our type map.
192 GSC_TYPEMAP_remove (const uint16_t *types,
201 if (0 == --map_counters[types[i]])
203 my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
204 changed = GNUNET_YES;
207 if (GNUNET_YES == changed)
208 broadcast_my_type_map ();
213 * Test if any of the types from the types array is in the
216 * @param map map to test
217 * @param types array of types
218 * @param tcnt number of entries in types
219 * @return GNUNET_YES if a type is in the map, GNUNET_NO if not
222 GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap,
223 const uint16_t *types,
231 if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
238 * Add additional types to a given typemap.
240 * @param map map to extend (not changed)
241 * @param types array of types to add
242 * @param tcnt number of entries in types
243 * @return updated type map (fresh copy)
246 GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
247 const uint16_t *types,
250 struct GSC_TypeMap *ret;
253 ret = GNUNET_malloc (sizeof (struct GSC_TypeMap));
255 memcpy (ret, tmap, sizeof (struct GSC_TypeMap));
257 ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
263 * Create an empty type map.
265 * @param map a type map
268 GSC_TYPEMAP_create ()
270 return GNUNET_malloc (sizeof (struct GSC_TypeMap));
275 * Free the given type map.
277 * @param map a type map
280 GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap)
287 * Initialize typemap subsystem.
297 * Shutdown typemap subsystem.
305 /* end of gnunet-service-core_typemap.c */