fixes
[oweals/gnunet.git] / src / core / gnunet-service-core_neighbours.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file core/gnunet-service-core_neighbours.c
23  * @brief code for managing low-level 'plaintext' connections with transport (key exchange may or may not be done yet)
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet_transport_service.h"
30 #include "gnunet-service-core.h"
31 #include "gnunet-service-core_neighbours.h"
32 #include "gnunet-service-core_kx.h"
33 #include "gnunet-service-core_sessions.h"
34 #include "gnunet_constants.h"
35
36
37 /**
38  * Message ready for transmission via transport service.  This struct
39  * is followed by the actual content of the message.
40  */
41 struct NeighbourMessageEntry
42 {
43
44   /**
45    * We keep messages in a doubly linked list.
46    */
47   struct NeighbourMessageEntry *next;
48
49   /**
50    * We keep messages in a doubly linked list.
51    */
52   struct NeighbourMessageEntry *prev;
53
54   /**
55    * By when are we supposed to transmit this message?
56    */
57   struct GNUNET_TIME_Absolute deadline;
58
59   /**
60    * How long is the message? (number of bytes following the "struct
61    * MessageEntry", but not including the size of "struct
62    * MessageEntry" itself!)
63    */
64   size_t size;
65
66 };
67
68
69 /**
70  * Data kept per transport-connected peer.
71  */
72 struct Neighbour
73 {
74
75   /**
76    * Head of the batched message queue (already ordered, transmit
77    * starting with the head).
78    */
79   struct NeighbourMessageEntry *message_head;
80
81   /**
82    * Tail of the batched message queue (already ordered, append new
83    * messages to tail).
84    */
85   struct NeighbourMessageEntry *message_tail;
86
87   /**
88    * Handle for pending requests for transmission to this peer
89    * with the transport service.  NULL if no request is pending.
90    */
91   struct GNUNET_TRANSPORT_TransmitHandle *th;
92
93   /**
94    * Information about the key exchange with the other peer.
95    */
96   struct GSC_KeyExchangeInfo *kxinfo;
97
98   /**
99    * Identity of the other peer.
100    */
101   struct GNUNET_PeerIdentity peer;
102
103   /**
104    * ID of task used for re-trying plaintext scheduling.
105    */
106   GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
107
108 };
109
110
111 /**
112  * Map of peer identities to 'struct Neighbour'.
113  */
114 static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
115
116 /**
117  * Transport service.
118  */
119 static struct GNUNET_TRANSPORT_Handle *transport;
120
121
122 /**
123  * Find the entry for the given neighbour.
124  *
125  * @param peer identity of the neighbour
126  * @return NULL if we are not connected, otherwise the
127  *         neighbour's entry.
128  */
129 static struct Neighbour *
130 find_neighbour (const struct GNUNET_PeerIdentity *peer)
131 {
132   return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
133 }
134
135
136 /**
137  * Free the given entry for the neighbour.
138  *
139  * @param n neighbour to free
140  */
141 static void
142 free_neighbour (struct Neighbour *n)
143 {
144   struct NeighbourMessageEntry *m;
145
146 #if DEBUG_CORE
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148               "Destroying neighbour entry for peer `%4s'\n",
149               GNUNET_i2s (&n->peer));
150 #endif
151   while (NULL != (m = n->message_head))
152   {
153     GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
154     GNUNET_free (m);
155   }
156   if (NULL != n->th)
157   {
158     GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
159     n->th = NULL;
160   }
161   GSC_SESSIONS_end (&n->peer);
162   if (NULL != n->kxinfo)
163   {
164     GSC_KX_stop (n->kxinfo);
165     n->kxinfo = NULL;
166   }
167   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
168   {
169     GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
170     n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
171   }
172   GNUNET_assert (GNUNET_OK ==
173                  GNUNET_CONTAINER_multihashmap_remove (neighbours,
174                                                        &n->peer.hashPubKey, n));
175   GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"),
176                          GNUNET_CONTAINER_multihashmap_size (neighbours),
177                          GNUNET_NO);
178   GNUNET_free (n);
179 }
180
181
182 /**
183  * Check if we have encrypted messages for the specified neighbour
184  * pending, and if so, check with the transport about sending them
185  * out.
186  *
187  * @param n neighbour to check.
188  */
189 static void
190 process_queue (struct Neighbour *n);
191
192
193 /**
194  * Function called when the transport service is ready to receive a
195  * message for the respective peer
196  *
197  * @param cls neighbour to use message from
198  * @param size number of bytes we can transmit
199  * @param buf where to copy the message
200  * @return number of bytes transmitted
201  */
202 static size_t
203 transmit_ready (void *cls, size_t size, void *buf)
204 {
205   struct Neighbour *n = cls;
206   struct NeighbourMessageEntry *m;
207   size_t ret;
208   char *cbuf;
209
210   n->th = NULL;
211   m = n->message_head;
212   if (m == NULL)
213   {
214     GNUNET_break (0);
215     return 0;
216   }
217   GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
218   if (buf == NULL)
219   {
220 #if DEBUG_CORE
221     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222                 "Transmission of message of type %u and size %u failed\n",
223                 (unsigned int)
224                 ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
225                 (unsigned int) m->size);
226 #endif
227     GNUNET_free (m);
228     process_queue (n);
229     return 0;
230   }
231   ret = 0;
232   cbuf = buf;
233   GNUNET_assert (size >= m->size);
234   memcpy (cbuf, &m[1], m->size);
235   ret = m->size;
236 #if DEBUG_CORE
237   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
238               "Copied message of type %u and size %u into transport buffer for `%4s'\n",
239               (unsigned int)
240               ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
241               (unsigned int) ret, GNUNET_i2s (&n->peer));
242 #endif
243   GNUNET_free (m);
244   process_queue (n);
245   GNUNET_STATISTICS_update (GSC_stats,
246                             gettext_noop
247                             ("# encrypted bytes given to transport"), ret,
248                             GNUNET_NO);
249   return ret;
250 }
251
252
253 /**
254  * Check if we have messages for the specified neighbour pending, and
255  * if so, check with the transport about sending them out.
256  *
257  * @param n neighbour to check.
258  */
259 static void
260 process_queue (struct Neighbour *n)
261 {
262   struct NeighbourMessageEntry *m;
263
264   if (n->th != NULL)
265     return;                     /* request already pending */
266   m = n->message_head;
267   if (m == NULL)
268   {
269     /* notify sessions that the queue is empty and more messages
270        could thus be queued now */
271     GSC_SESSIONS_solicit (&n->peer);
272     return;
273   }
274 #if DEBUG_CORE > 1
275   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276               "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
277               (unsigned int) m->size, GNUNET_i2s (&n->peer),
278               (unsigned long long)
279               GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
280 #endif
281   n->th =
282        GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size,
283                                                0,
284                                                GNUNET_TIME_absolute_get_remaining
285                                                (m->deadline),
286                                                &transmit_ready,
287                                                n);
288   if (n->th != NULL)
289     return;
290   /* message request too large or duplicate request */
291   GNUNET_break (0);
292   /* discard encrypted message */
293   GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
294   GNUNET_free (m);
295   process_queue (n);
296 }
297
298
299
300 /**
301  * Function called by transport to notify us that
302  * a peer connected to us (on the network level).
303  *
304  * @param cls closure
305  * @param peer the peer that connected
306  * @param ats performance data
307  * @param ats_count number of entries in ats (excluding 0-termination)
308  */
309 static void
310 handle_transport_notify_connect (void *cls,
311                                  const struct GNUNET_PeerIdentity *peer,
312                                  const struct GNUNET_TRANSPORT_ATS_Information
313                                  *ats, uint32_t ats_count)
314 {
315   struct Neighbour *n;
316
317   if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
318   {
319     GNUNET_break (0);
320     return;
321   }
322   n = find_neighbour (peer);
323   if (n != NULL)
324   {
325     /* duplicate connect notification!? */
326     GNUNET_break (0);
327     return;
328   }
329 #if DEBUG_CORE
330   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received connection from `%4s'.\n",
331               GNUNET_i2s (peer));
332 #endif
333   n = GNUNET_malloc (sizeof (struct Neighbour));
334   n->peer = *peer;
335   GNUNET_assert (GNUNET_OK ==
336                  GNUNET_CONTAINER_multihashmap_put (neighbours,
337                                                     &n->peer.hashPubKey, n,
338                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
339   GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"),
340                          GNUNET_CONTAINER_multihashmap_size (neighbours),
341                          GNUNET_NO);
342   n->kxinfo = GSC_KX_start (peer);
343 }
344
345
346 /**
347  * Function called by transport telling us that a peer
348  * disconnected.
349  *
350  * @param cls closure
351  * @param peer the peer that disconnected
352  */
353 static void
354 handle_transport_notify_disconnect (void *cls,
355                                     const struct GNUNET_PeerIdentity *peer)
356 {
357   struct Neighbour *n;
358
359 #if DEBUG_CORE
360   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361               "Peer `%4s' disconnected from us; received notification from transport.\n",
362               GNUNET_i2s (peer));
363 #endif
364   n = find_neighbour (peer);
365   if (n == NULL)
366   {
367     GNUNET_break (0);
368     return;
369   }
370   free_neighbour (n);
371 }
372
373
374 /**
375  * Function called by the transport for each received message.
376  *
377  * @param cls closure
378  * @param peer (claimed) identity of the other peer
379  * @param message the message
380  * @param ats performance data
381  * @param ats_count number of entries in ats (excluding 0-termination)
382  */
383 static void
384 handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
385                           const struct GNUNET_MessageHeader *message,
386                           const struct GNUNET_TRANSPORT_ATS_Information *ats,
387                           uint32_t ats_count)
388 {
389   struct Neighbour *n;
390   uint16_t type;
391
392 #if DEBUG_CORE > 1
393   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394               "Received message of type %u from `%4s', demultiplexing.\n",
395               (unsigned int) ntohs (message->type), GNUNET_i2s (peer));
396 #endif
397   if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
398   {
399     GNUNET_break (0);
400     return;
401   }
402   n = find_neighbour (peer);
403   if (n == NULL)
404   {
405     /* received message from peer that is not connected!? */
406     GNUNET_break (0);
407     return;
408   }
409   type = ntohs (message->type);
410   switch (type)
411   {
412   case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
413     GSC_KX_handle_set_key (n->kxinfo, message);
414     break;
415   case GNUNET_MESSAGE_TYPE_CORE_PING:
416     GSC_KX_handle_ping (n->kxinfo, message);
417     break;
418   case GNUNET_MESSAGE_TYPE_CORE_PONG:
419     GSC_KX_handle_pong (n->kxinfo, message);
420     break;
421   case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
422     GSC_KX_handle_encrypted_message (n->kxinfo,
423                                      message, ats,
424                                      ats_count);
425     break;
426   default:
427     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
428                 _("Unsupported message of type %u received.\n"),
429                 (unsigned int) type);
430     return;
431   }
432 }
433
434
435 /**
436  * Transmit the given message to the given target.
437  * 
438  * @param target peer that should receive the message (must be connected)
439  * @param msg message to transmit
440  * @param timeout by when should the transmission be done?
441  */
442 void
443 GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
444                          const struct GNUNET_MessageHeader *msg,
445                          struct GNUNET_TIME_Relative timeout)
446 {
447   struct NeighbourMessageEntry *me;
448   struct Neighbour *n;
449   size_t msize;
450
451   n = find_neighbour (target);
452   if (NULL == n)
453   {
454     GNUNET_break (0);
455     return;
456   }
457   msize = ntohs (msg->size);
458   me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize);
459   me->deadline = GNUNET_TIME_relative_to_absolute (timeout);
460   me->size = msize;
461   memcpy (&me[1], msg, msize);
462   GNUNET_CONTAINER_DLL_insert_tail (n->message_head,
463                                     n->message_tail,
464                                     me);
465   process_queue (n);
466 }
467
468
469 /**
470  * Initialize neighbours subsystem.
471  */
472 int
473 GSC_NEIGHBOURS_init ()
474 {
475   neighbours = GNUNET_CONTAINER_multihashmap_create (128);
476   transport =
477       GNUNET_TRANSPORT_connect (GSC_cfg, 
478                                 &GSC_my_identity, NULL,
479                                 &handle_transport_receive,
480                                 &handle_transport_notify_connect,
481                                 &handle_transport_notify_disconnect);
482   if (NULL == transport)
483   {
484     GNUNET_CONTAINER_multihashmap_destroy (neighbours);
485     neighbours = NULL;
486     return GNUNET_SYSERR;
487   }
488   return GNUNET_OK;
489 }
490
491
492 /**
493  * Wrapper around 'free_neighbour'.
494  *
495  * @param cls unused
496  * @param key peer identity
497  * @param value the 'struct Neighbour' to free
498  * @return GNUNET_OK (continue to iterate)
499  */
500 static int
501 free_neighbour_helper (void *cls, const GNUNET_HashCode * key, void *value)
502 {
503   struct Neighbour *n = value;
504
505   free_neighbour (n);
506   return GNUNET_OK;
507 }
508
509
510 /**
511  * Shutdown neighbours subsystem.
512  */
513 void
514 GSC_NEIGHBOURS_done ()
515 {
516   if (NULL == transport)
517     return;
518   GNUNET_CONTAINER_multihashmap_iterate (neighbours, &free_neighbour_helper,
519                                          NULL);
520   GNUNET_TRANSPORT_disconnect (transport);
521   transport = NULL;
522   GNUNET_CONTAINER_multihashmap_destroy (neighbours);
523   neighbours = NULL;
524 }
525
526 /* end of gnunet-service-core_neighbours.c */
527