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