13593e9d67698248e887e400524c41c31e3af3a3
[oweals/gnunet.git] / src / core / gnunet-service-core_sessions.c
1 /* code for managing of 'encrypted' sessions (key exchange done) */
2
3
4 /**
5  * Record kept for each request for transmission issued by a
6  * client that is still pending.
7  */
8 struct ClientActiveRequest;
9
10 /**
11  * Data kept per session.
12  */
13 struct Session
14 {
15   /**
16    * Identity of the other peer.
17    */
18   struct GNUNET_PeerIdentity peer;
19
20   /**
21    * Head of list of requests from clients for transmission to
22    * this peer.
23    */
24   struct ClientActiveRequest *active_client_request_head;
25
26   /**
27    * Tail of list of requests from clients for transmission to
28    * this peer.
29    */
30   struct ClientActiveRequest *active_client_request_tail;
31
32   /**
33    * Performance data for the peer.
34    */
35   struct GNUNET_TRANSPORT_ATS_Information *ats;
36
37   /**
38    * Information about the key exchange with the other peer.
39    */
40   struct GSC_KeyExchangeInfo *kxinfo;
41
42   /**
43    * ID of task used for sending keep-alive pings.
44    */
45   GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
46
47   /**
48    * ID of task used for cleaning up dead neighbour entries.
49    */
50   GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
51
52   /**
53    * ID of task used for updating bandwidth quota for this neighbour.
54    */
55   GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
56
57   /**
58    * At what time did we initially establish (as in, complete session
59    * key handshake) this connection?  Should be zero if status != KEY_CONFIRMED.
60    */
61   struct GNUNET_TIME_Absolute time_established;
62
63   /**
64    * At what time did we last receive an encrypted message from the
65    * other peer?  Should be zero if status != KEY_CONFIRMED.
66    */
67   struct GNUNET_TIME_Absolute last_activity;
68
69   /**
70    * Tracking bandwidth for sending to this peer.
71    */
72   struct GNUNET_BANDWIDTH_Tracker available_send_window;
73
74   /**
75    * Tracking bandwidth for receiving from this peer.
76    */
77   struct GNUNET_BANDWIDTH_Tracker available_recv_window;
78
79   /**
80    * How valueable were the messages of this peer recently?
81    */
82   unsigned long long current_preference;
83
84   /**
85    * Number of entries in 'ats'.
86    */
87   unsigned int ats_count;
88
89   /**
90    * Bit map indicating which of the 32 sequence numbers before the last
91    * were received (good for accepting out-of-order packets and
92    * estimating reliability of the connection)
93    */
94   unsigned int last_packets_bitmap;
95
96   /**
97    * last sequence number received on this connection (highest)
98    */
99   uint32_t last_sequence_number_received;
100
101   /**
102    * last sequence number transmitted
103    */
104   uint32_t last_sequence_number_sent;
105
106   /**
107    * Available bandwidth in for this peer (current target).
108    */
109   struct GNUNET_BANDWIDTH_Value32NBO bw_in;
110
111   /**
112    * Available bandwidth out for this peer (current target).
113    */
114   struct GNUNET_BANDWIDTH_Value32NBO bw_out;
115
116   /**
117    * Internal bandwidth limit set for this peer (initially typically
118    * set to "-1").  Actual "bw_out" is MIN of
119    * "bpm_out_internal_limit" and "bw_out_external_limit".
120    */
121   struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
122
123   /**
124    * External bandwidth limit set for this peer by the
125    * peer that we are communicating with.  "bw_out" is MIN of
126    * "bw_out_internal_limit" and "bw_out_external_limit".
127    */
128   struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
129
130 };
131
132
133 /**
134  * Map of peer identities to 'struct Session'.
135  */
136 static struct GNUNET_CONTAINER_MultiHashMap *sessions;
137
138
139 /**
140  * Session entry for "this" peer.
141  */
142 static struct Session self;
143
144 /**
145  * Sum of all preferences among all neighbours.
146  */
147 static unsigned long long preference_sum;
148
149
150 // FIXME.........
151
152 /**
153  * At what time should the connection to the given neighbour
154  * time out (given no further activity?)
155  *
156  * @param n neighbour in question
157  * @return absolute timeout
158  */
159 static struct GNUNET_TIME_Absolute
160 get_neighbour_timeout (struct Neighbour *n)
161 {
162   return GNUNET_TIME_absolute_add (n->last_activity,
163                                    GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
164 }
165
166
167 /**
168  * Helper function for update_preference_sum.
169  */
170 static int
171 update_preference (void *cls, const GNUNET_HashCode * key, void *value)
172 {
173   unsigned long long *ps = cls;
174   struct Neighbour *n = value;
175
176   n->current_preference /= 2;
177   *ps += n->current_preference;
178   return GNUNET_OK;
179 }
180
181
182 /**
183  * A preference value for a neighbour was update.  Update
184  * the preference sum accordingly.
185  *
186  * @param inc how much was a preference value increased?
187  */
188 static void
189 update_preference_sum (unsigned long long inc)
190 {
191   unsigned long long os;
192
193   os = preference_sum;
194   preference_sum += inc;
195   if (preference_sum >= os)
196     return;                     /* done! */
197   /* overflow! compensate by cutting all values in half! */
198   preference_sum = 0;
199   GNUNET_CONTAINER_multihashmap_iterate (neighbours, &update_preference,
200                                          &preference_sum);
201   GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"),
202                          preference_sum, GNUNET_NO);
203 }
204
205
206 /**
207  * Find the entry for the given neighbour.
208  *
209  * @param peer identity of the neighbour
210  * @return NULL if we are not connected, otherwise the
211  *         neighbour's entry.
212  */
213 static struct Neighbour *
214 find_neighbour (const struct GNUNET_PeerIdentity *peer)
215 {
216   return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
217 }
218
219
220 /**
221  * Function called by transport telling us that a peer
222  * changed status.
223  *
224  * @param n the peer that changed status
225  */
226 static void
227 handle_peer_status_change (struct Neighbour *n)
228 {
229   struct PeerStatusNotifyMessage *psnm;
230   char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
231   struct GNUNET_TRANSPORT_ATS_Information *ats;
232   size_t size;
233
234   if ((!n->is_connected) || (n->status != PEER_STATE_KEY_CONFIRMED))
235     return;
236 #if DEBUG_CORE > 1
237   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' changed status\n",
238               GNUNET_i2s (&n->peer));
239 #endif
240   size =
241       sizeof (struct PeerStatusNotifyMessage) +
242       n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
243   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
244   {
245     GNUNET_break (0);
246     /* recovery strategy: throw away performance data */
247     GNUNET_array_grow (n->ats, n->ats_count, 0);
248     size =
249         sizeof (struct PeerStatusNotifyMessage) +
250         n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
251   }
252   psnm = (struct PeerStatusNotifyMessage *) buf;
253   psnm->header.size = htons (size);
254   psnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
255   psnm->timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
256   psnm->bandwidth_in = n->bw_in;
257   psnm->bandwidth_out = n->bw_out;
258   psnm->peer = n->peer;
259   psnm->ats_count = htonl (n->ats_count);
260   ats = &psnm->ats;
261   memcpy (ats, n->ats,
262           n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
263   ats[n->ats_count].type = htonl (0);
264   ats[n->ats_count].value = htonl (0);
265   send_to_all_clients (&psnm->header, GNUNET_YES,
266                        GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
267   GNUNET_STATISTICS_update (stats, gettext_noop ("# peer status changes"), 1,
268                             GNUNET_NO);
269 }
270
271
272
273 /**
274  * Go over our message queue and if it is not too long, go
275  * over the pending requests from clients for this
276  * neighbour and send some clients a 'READY' notification.
277  *
278  * @param n which peer to process
279  */
280 static void
281 schedule_peer_messages (struct Neighbour *n)
282 {
283   struct SendMessageReady smr;
284   struct ClientActiveRequest *car;
285   struct ClientActiveRequest *pos;
286   struct Client *c;
287   struct MessageEntry *mqe;
288   unsigned int queue_size;
289
290   /* check if neighbour queue is empty enough! */
291   if (n != &self)
292   {
293     queue_size = 0;
294     mqe = n->messages;
295     while (mqe != NULL)
296     {
297       queue_size++;
298       mqe = mqe->next;
299     }
300     if (queue_size >= MAX_PEER_QUEUE_SIZE)
301     {
302 #if DEBUG_CORE_CLIENT
303       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304                   "Not considering client transmission requests: queue full\n");
305 #endif
306       return;                   /* queue still full */
307     }
308     /* find highest priority request */
309     pos = n->active_client_request_head;
310     car = NULL;
311     while (pos != NULL)
312     {
313       if ((car == NULL) || (pos->priority > car->priority))
314         car = pos;
315       pos = pos->next;
316     }
317   }
318   else
319   {
320     car = n->active_client_request_head;
321   }
322   if (car == NULL)
323     return;                     /* no pending requests */
324 #if DEBUG_CORE_CLIENT
325   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326               "Permitting client transmission request to `%s'\n",
327               GNUNET_i2s (&n->peer));
328 #endif
329   c = car->client;
330   GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
331                                n->active_client_request_tail, car);
332   GNUNET_assert (GNUNET_YES ==
333                  GNUNET_CONTAINER_multihashmap_remove (c->requests,
334                                                        &n->peer.hashPubKey,
335                                                        car));
336   smr.header.size = htons (sizeof (struct SendMessageReady));
337   smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
338   smr.size = htons (car->msize);
339   smr.smr_id = car->smr_id;
340   smr.peer = n->peer;
341   send_to_client (c, &smr.header, GNUNET_NO);
342   GNUNET_free (car);
343 }
344
345
346
347 /**
348  * Free the given entry for the neighbour (it has
349  * already been removed from the list at this point).
350  *
351  * @param n neighbour to free
352  */
353 static void
354 free_neighbour (struct Neighbour *n)
355 {
356   struct MessageEntry *m;
357   struct ClientActiveRequest *car;
358
359 #if DEBUG_CORE
360   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361               "Destroying neighbour entry for peer `%4s'\n",
362               GNUNET_i2s (&n->peer));
363 #endif
364   if (n->skm != NULL)
365   {
366     GNUNET_free (n->skm);
367     n->skm = NULL;
368   }
369   while (NULL != (m = n->messages))
370   {
371     n->messages = m->next;
372     GNUNET_free (m);
373   }
374   while (NULL != (m = n->encrypted_head))
375   {
376     GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
377     GNUNET_free (m);
378   }
379   while (NULL != (car = n->active_client_request_head))
380   {
381     GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
382                                  n->active_client_request_tail, car);
383     GNUNET_assert (GNUNET_YES ==
384                    GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
385                                                          &n->peer.hashPubKey,
386                                                          car));
387     GNUNET_free (car);
388   }
389   if (NULL != n->th)
390   {
391     GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
392     n->th = NULL;
393   }
394   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
395     GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
396   if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
397     GNUNET_SCHEDULER_cancel (n->quota_update_task);
398   if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
399     GNUNET_SCHEDULER_cancel (n->dead_clean_task);
400   if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
401     GNUNET_SCHEDULER_cancel (n->keep_alive_task);
402   if (n->status == PEER_STATE_KEY_CONFIRMED)
403     GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"),
404                               -1, GNUNET_NO);
405   GNUNET_array_grow (n->ats, n->ats_count, 0);
406   GNUNET_free_non_null (n->pending_ping);
407   GNUNET_free_non_null (n->pending_pong);
408   GNUNET_free (n);
409 }
410
411
412
413 /**
414  * Task triggered when a neighbour entry is about to time out
415  * (and we should prevent this by sending a PING).
416  *
417  * @param cls the 'struct Neighbour'
418  * @param tc scheduler context (not used)
419  */
420 static void
421 send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
422 {
423   struct Neighbour *n = cls;
424   struct GNUNET_TIME_Relative retry;
425   struct GNUNET_TIME_Relative left;
426   struct MessageEntry *me;
427   struct PingMessage pp;
428   struct PingMessage *pm;
429   struct GNUNET_CRYPTO_AesInitializationVector iv;
430
431   n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
432   /* send PING */
433   me = GNUNET_malloc (sizeof (struct MessageEntry) +
434                       sizeof (struct PingMessage));
435   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY);
436   me->priority = PING_PRIORITY;
437   me->size = sizeof (struct PingMessage);
438   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head, n->encrypted_tail,
439                                      n->encrypted_tail, me);
440   pm = (struct PingMessage *) &me[1];
441   pm->header.size = htons (sizeof (struct PingMessage));
442   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
443   pm->iv_seed =
444       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
445   derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
446   pp.challenge = n->ping_challenge;
447   pp.target = n->peer;
448 #if DEBUG_HANDSHAKE
449   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
450               "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
451               "PING", (unsigned int) n->ping_challenge, GNUNET_i2s (&n->peer),
452               (unsigned int) n->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (&iv,
453                                                                           sizeof
454                                                                           (iv)),
455               pm->iv_seed);
456 #endif
457   do_encrypt (n, &iv, &pp.target, &pm->target,
458               sizeof (struct PingMessage) - ((void *) &pm->target -
459                                              (void *) pm));
460   process_encrypted_neighbour_queue (n);
461   /* reschedule PING job */
462   left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
463   retry =
464       GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
465                                 MIN_PING_FREQUENCY);
466   n->keep_alive_task =
467       GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, n);
468
469 }
470
471 /**
472  * Consider freeing the given neighbour since we may not need
473  * to keep it around anymore.
474  *
475  * @param n neighbour to consider discarding
476  */
477 static void
478 consider_free_neighbour (struct Neighbour *n);
479
480
481 /**
482  * Task triggered when a neighbour entry might have gotten stale.
483  *
484  * @param cls the 'struct Neighbour'
485  * @param tc scheduler context (not used)
486  */
487 static void
488 consider_free_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
489 {
490   struct Neighbour *n = cls;
491
492   n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
493   consider_free_neighbour (n);
494 }
495
496
497 /**
498  * Consider freeing the given neighbour since we may not need
499  * to keep it around anymore.
500  *
501  * @param n neighbour to consider discarding
502  */
503 static void
504 consider_free_neighbour (struct Neighbour *n)
505 {
506   struct GNUNET_TIME_Relative left;
507
508   if ((n->th != NULL) || (n->pitr != NULL) || (GNUNET_YES == n->is_connected))
509     return;                     /* no chance */
510
511   left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
512   if (left.rel_value > 0)
513   {
514     if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
515       GNUNET_SCHEDULER_cancel (n->dead_clean_task);
516     n->dead_clean_task =
517         GNUNET_SCHEDULER_add_delayed (left, &consider_free_task, n);
518     return;
519   }
520   /* actually free the neighbour... */
521   GNUNET_assert (GNUNET_YES ==
522                  GNUNET_CONTAINER_multihashmap_remove (neighbours,
523                                                        &n->peer.hashPubKey, n));
524   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
525                          GNUNET_CONTAINER_multihashmap_size (neighbours),
526                          GNUNET_NO);
527   free_neighbour (n);
528 }
529
530
531 /**
532  * Function called when the transport service is ready to
533  * receive an encrypted message for the respective peer
534  *
535  * @param cls neighbour to use message from
536  * @param size number of bytes we can transmit
537  * @param buf where to copy the message
538  * @return number of bytes transmitted
539  */
540 static size_t
541 notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
542 {
543   struct Neighbour *n = cls;
544   struct MessageEntry *m;
545   size_t ret;
546   char *cbuf;
547
548   n->th = NULL;
549   m = n->encrypted_head;
550   if (m == NULL)
551   {
552 #if DEBUG_CORE
553     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
554                 "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
555                 GNUNET_i2s (&n->peer));
556 #endif
557     return 0;
558   }
559   GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
560   ret = 0;
561   cbuf = buf;
562   if (buf != NULL)
563   {
564     GNUNET_assert (size >= m->size);
565     memcpy (cbuf, &m[1], m->size);
566     ret = m->size;
567     GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window, m->size);
568 #if DEBUG_CORE
569     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
570                 "Copied message of type %u and size %u into transport buffer for `%4s'\n",
571                 (unsigned int)
572                 ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
573                 (unsigned int) ret, GNUNET_i2s (&n->peer));
574 #endif
575     process_encrypted_neighbour_queue (n);
576   }
577   else
578   {
579 #if DEBUG_CORE
580     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
581                 "Transmission of message of type %u and size %u failed\n",
582                 (unsigned int)
583                 ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
584                 (unsigned int) m->size);
585 #endif
586   }
587   GNUNET_free (m);
588   consider_free_neighbour (n);
589   GNUNET_STATISTICS_update (stats,
590                             gettext_noop
591                             ("# encrypted bytes given to transport"), ret,
592                             GNUNET_NO);
593   return ret;
594 }
595
596
597 /**
598  * Check if we have encrypted messages for the specified neighbour
599  * pending, and if so, check with the transport about sending them
600  * out.
601  *
602  * @param n neighbour to check.
603  */
604 static void
605 process_encrypted_neighbour_queue (struct Neighbour *n)
606 {
607   struct MessageEntry *m;
608
609   if (n->th != NULL)
610     return;                     /* request already pending */
611   if (GNUNET_YES != n->is_connected)
612   {
613     GNUNET_break (0);
614     return;
615   }
616   m = n->encrypted_head;
617   if (m == NULL)
618   {
619     /* encrypted queue empty, try plaintext instead */
620     process_plaintext_neighbour_queue (n);
621     return;
622   }
623 #if DEBUG_CORE > 1
624   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
625               "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
626               (unsigned int) m->size, GNUNET_i2s (&n->peer),
627               (unsigned long long)
628               GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
629 #endif
630   n->th =
631        GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size,
632                                               m->priority,
633                                               GNUNET_TIME_absolute_get_remaining
634                                               (m->deadline),
635                                               &notify_encrypted_transmit_ready,
636                                               n);
637   if (n->th == NULL)
638   {
639     /* message request too large or duplicate request */
640     GNUNET_break (0);
641     /* discard encrypted message */
642     GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
643     GNUNET_free (m);
644     process_encrypted_neighbour_queue (n);
645   }
646 }
647
648
649 /**
650  * Initialize a new 'struct Neighbour'.
651  *
652  * @param pid ID of the new neighbour
653  * @return handle for the new neighbour
654  */
655 static struct Neighbour *
656 create_neighbour (const struct GNUNET_PeerIdentity *pid)
657 {
658   struct Neighbour *n;
659   struct GNUNET_TIME_Absolute now;
660
661 #if DEBUG_CORE
662   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663               "Creating neighbour entry for peer `%4s'\n", GNUNET_i2s (pid));
664 #endif
665   n = GNUNET_malloc (sizeof (struct Neighbour));
666   n->peer = *pid;
667   GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
668   now = GNUNET_TIME_absolute_get ();
669   n->encrypt_key_created = now;
670   n->last_activity = now;
671   n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
672   n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
673   n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
674   n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
675   n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
676   n->ping_challenge =
677       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
678   GNUNET_assert (GNUNET_OK ==
679                  GNUNET_CONTAINER_multihashmap_put (neighbours,
680                                                     &n->peer.hashPubKey, n,
681                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
682   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
683                          GNUNET_CONTAINER_multihashmap_size (neighbours),
684                          GNUNET_NO);
685   neighbour_quota_update (n, NULL);
686   consider_free_neighbour (n);
687   return n;
688 }
689
690
691 int
692 GSC_NEIGHBOURS_init ()
693 {
694   neighbours = GNUNET_CONTAINER_multihashmap_create (128);
695   self.public_key = &my_public_key;
696   self.peer = my_identity;
697   self.last_activity = GNUNET_TIME_UNIT_FOREVER_ABS;
698   self.status = PEER_STATE_KEY_CONFIRMED;
699   self.is_connected = GNUNET_YES;
700   return GNUNET_OK;
701 }
702
703
704 void
705 GSC_NEIGHBOURS_done ()
706 {
707   GNUNET_CONTAINER_multihashmap_iterate (neighbours, &free_neighbour_helper,
708                                          NULL);
709   GNUNET_CONTAINER_multihashmap_destroy (neighbours);
710   neighbours = NULL;
711   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
712                          0, GNUNET_NO);
713 }