dfd0b88882eaf48101b5e64894a502a04b696f62
[oweals/gnunet.git] / src / core / gnunet-service-core_typemap.c
1
2 /**
3  * A type map describing which messages a given neighbour is able
4  * to process.
5  */
6 struct GSC_TypeMap 
7 {
8   uint32_t bits[(UINT16_MAX + 1) / 32];
9 };
10
11
12 /**
13  * Bitmap of message types this peer is able to handle.
14  */
15 static uint32_t my_type_map[(UINT16_MAX + 1) / 32];
16
17
18 /**
19  * Add a set of types to our type map.
20  */
21 void
22 GSC_TYPEMAP_add (const uint16_t *types,
23                  unsigned int tlen)
24 {
25   unsigned int i;
26
27   for (i=0;i<tlen;i++)
28     my_type_map[types[i] / 32] |= (1 << (types[i] % 32));
29   if (tlen > 0)
30     broadcast_my_type_map ();
31 }
32
33
34 /**
35  * Remove a set of types from our type map.
36  */
37 void
38 GSC_TYPEMAP_remove (const uint16_t *types,
39                     unsigned int tlen)
40 {
41   /* rebuild my_type_map */
42   memset (my_type_map, 0, sizeof (my_type_map));
43   for (pos = clients; NULL != pos; pos = pos->next)
44   {
45     wtypes = (const uint16_t *) &pos[1];
46     for (i = 0; i < pos->tcnt; i++)
47       my_type_map[wtypes[i] / 32] |= (1 << (wtypes[i] % 32));
48   }
49   broadcast_my_type_map ();
50 }
51
52
53 /**
54  * Test if any of the types from the types array is in the
55  * given type map.
56  *
57  * @param map map to test
58  * @param types array of types
59  * @param tcnt number of entries in types
60  * @return GNUNET_YES if a type is in the map, GNUNET_NO if not
61  */ 
62 int
63 GSC_TYPEMAP_test_match (struct GSC_TypeMap *tmap,
64                         const uint16_t *types,
65                         unsigned int tcnt)
66 {
67   return GNUNET_YES; /* FIXME */
68 }
69
70
71 /**
72  * Compute a type map message for this peer.
73  *
74  * @return this peers current type map message.
75  */
76 static struct GNUNET_MessageHeader *
77 compute_type_map_message ()
78 {
79   char *tmp;
80   uLongf dlen;
81   struct GNUNET_MessageHeader *hdr;
82
83 #ifdef compressBound
84   dlen = compressBound (sizeof (my_type_map));
85 #else
86   dlen = sizeof (my_type_map) + (sizeof (my_type_map) / 100) + 20;
87   /* documentation says 100.1% oldSize + 12 bytes, but we
88    * should be able to overshoot by more to be safe */
89 #endif
90   hdr = GNUNET_malloc (dlen + sizeof (struct GNUNET_MessageHeader));
91   hdr->size = htons ((uint16_t) dlen + sizeof (struct GNUNET_MessageHeader));
92   tmp = (char *) &hdr[1];
93   if ((Z_OK !=
94        compress2 ((Bytef *) tmp, &dlen, (const Bytef *) my_type_map,
95                   sizeof (my_type_map), 9)) || (dlen >= sizeof (my_type_map)))
96   {
97     dlen = sizeof (my_type_map);
98     memcpy (tmp, my_type_map, sizeof (my_type_map));
99     hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP);
100   }
101   else
102   {
103     hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP);
104   }
105   return hdr;
106 }
107
108
109 /**
110  * Send a type map message to the neighbour.
111  *
112  * @param cls the type map message
113  * @param key neighbour's identity
114  * @param value 'struct Neighbour' of the target
115  * @return always GNUNET_OK
116  */
117 static int
118 send_type_map_to_neighbour (void *cls, const GNUNET_HashCode * key, void *value)
119 {
120   struct GNUNET_MessageHeader *hdr = cls;
121   struct Neighbour *n = value;
122   struct MessageEntry *m;
123   uint16_t size;
124
125   if (n == &self)
126     return GNUNET_OK;
127   size = ntohs (hdr->size);
128   m = GNUNET_malloc (sizeof (struct MessageEntry) + size);
129   memcpy (&m[1], hdr, size);
130   m->deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
131   m->slack_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
132   m->priority = UINT_MAX;
133   m->sender_status = n->status;
134   m->size = size;
135   m->next = n->messages;
136   n->messages = m;
137   return GNUNET_OK;
138 }
139
140
141
142 /**
143  * Send my type map to all connected peers (it got changed).
144  */
145 static void
146 broadcast_my_type_map ()
147 {
148   struct GNUNET_MessageHeader *hdr;
149
150   if (NULL == neighbours)
151     return;
152   hdr = compute_type_map_message ();
153   GNUNET_CONTAINER_multihashmap_iterate (neighbours,
154                                          &send_type_map_to_neighbour, hdr);
155   GNUNET_free (hdr);
156 }
157
158
159