aboutsummaryrefslogtreecommitdiff
path: root/src/core/gnunet-service-core_typemap.c
blob: 3aa652999c8be944061504247d79f71146eb187b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
 * Bitmap of message types this peer is able to handle.
 */
static uint32_t my_type_map[(UINT16_MAX + 1) / 32];


/**
 * Compute a type map message for this peer.
 *
 * @return this peers current type map message.
 */
static struct GNUNET_MessageHeader *
compute_type_map_message ()
{
  char *tmp;
  uLongf dlen;
  struct GNUNET_MessageHeader *hdr;

#ifdef compressBound
  dlen = compressBound (sizeof (my_type_map));
#else
  dlen = sizeof (my_type_map) + (sizeof (my_type_map) / 100) + 20;
  /* documentation says 100.1% oldSize + 12 bytes, but we
   * should be able to overshoot by more to be safe */
#endif
  hdr = GNUNET_malloc (dlen + sizeof (struct GNUNET_MessageHeader));
  hdr->size = htons ((uint16_t) dlen + sizeof (struct GNUNET_MessageHeader));
  tmp = (char *) &hdr[1];
  if ((Z_OK !=
       compress2 ((Bytef *) tmp, &dlen, (const Bytef *) my_type_map,
                  sizeof (my_type_map), 9)) || (dlen >= sizeof (my_type_map)))
  {
    dlen = sizeof (my_type_map);
    memcpy (tmp, my_type_map, sizeof (my_type_map));
    hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP);
  }
  else
  {
    hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP);
  }
  return hdr;
}


/**
 * Send a type map message to the neighbour.
 *
 * @param cls the type map message
 * @param key neighbour's identity
 * @param value 'struct Neighbour' of the target
 * @return always GNUNET_OK
 */
static int
send_type_map_to_neighbour (void *cls, const GNUNET_HashCode * key, void *value)
{
  struct GNUNET_MessageHeader *hdr = cls;
  struct Neighbour *n = value;
  struct MessageEntry *m;
  uint16_t size;

  if (n == &self)
    return GNUNET_OK;
  size = ntohs (hdr->size);
  m = GNUNET_malloc (sizeof (struct MessageEntry) + size);
  memcpy (&m[1], hdr, size);
  m->deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
  m->slack_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
  m->priority = UINT_MAX;
  m->sender_status = n->status;
  m->size = size;
  m->next = n->messages;
  n->messages = m;
  return GNUNET_OK;
}



/**
 * Send my type map to all connected peers (it got changed).
 */
static void
broadcast_my_type_map ()
{
  struct GNUNET_MessageHeader *hdr;

  if (NULL == neighbours)
    return;
  hdr = compute_type_map_message ();
  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
                                         &send_type_map_to_neighbour, hdr);
  GNUNET_free (hdr);
}