-improve UDP logging
[oweals/gnunet.git] / src / core / gnunet-service-core_neighbours.c
1 /*
2      This file is part of GNUnet.
3      Copyright (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   struct GNUNET_SCHEDULER_Task * retry_plaintext_task;
107
108   /**
109    * #GNUNET_YES if this peer currently has excess bandwidth.
110    */
111   int has_excess_bandwidth;
112
113 };
114
115
116 /**
117  * Map of peer identities to 'struct Neighbour'.
118  */
119 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
120
121 /**
122  * Transport service.
123  */
124 static struct GNUNET_TRANSPORT_Handle *transport;
125
126
127 /**
128  * Find the entry for the given neighbour.
129  *
130  * @param peer identity of the neighbour
131  * @return NULL if we are not connected, otherwise the
132  *         neighbour's entry.
133  */
134 static struct Neighbour *
135 find_neighbour (const struct GNUNET_PeerIdentity *peer)
136 {
137   if (NULL == neighbours)
138     return NULL;
139   return GNUNET_CONTAINER_multipeermap_get (neighbours, peer);
140 }
141
142
143 /**
144  * Free the given entry for the neighbour.
145  *
146  * @param n neighbour to free
147  */
148 static void
149 free_neighbour (struct Neighbour *n)
150 {
151   struct NeighbourMessageEntry *m;
152
153   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154               "Destroying neighbour entry for peer `%4s'\n",
155               GNUNET_i2s (&n->peer));
156   while (NULL != (m = n->message_head))
157   {
158     GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
159     GNUNET_free (m);
160   }
161   if (NULL != n->th)
162   {
163     GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
164     n->th = NULL;
165   }
166   GNUNET_STATISTICS_update (GSC_stats,
167                             gettext_noop
168                             ("# sessions terminated by transport disconnect"),
169                             1, GNUNET_NO);
170   if (NULL != n->kxinfo)
171   {
172     GSC_KX_stop (n->kxinfo);
173     n->kxinfo = NULL;
174   }
175   if (n->retry_plaintext_task != NULL)
176   {
177     GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
178     n->retry_plaintext_task = NULL;
179   }
180   GNUNET_assert (GNUNET_OK ==
181                  GNUNET_CONTAINER_multipeermap_remove (neighbours,
182                                                        &n->peer, n));
183   GNUNET_STATISTICS_set (GSC_stats,
184                          gettext_noop ("# neighbour entries allocated"),
185                          GNUNET_CONTAINER_multipeermap_size (neighbours),
186                          GNUNET_NO);
187   GNUNET_free (n);
188 }
189
190
191 /**
192  * Check if we have encrypted messages for the specified neighbour
193  * pending, and if so, check with the transport about sending them
194  * out.
195  *
196  * @param n neighbour to check.
197  */
198 static void
199 process_queue (struct Neighbour *n);
200
201
202 /**
203  * Function called when the transport service is ready to receive a
204  * message for the respective peer
205  *
206  * @param cls neighbour to use message from
207  * @param size number of bytes we can transmit
208  * @param buf where to copy the message
209  * @return number of bytes transmitted
210  */
211 static size_t
212 transmit_ready (void *cls, size_t size, void *buf)
213 {
214   struct Neighbour *n = cls;
215   struct NeighbourMessageEntry *m;
216   size_t ret;
217   char *cbuf;
218
219   n->th = NULL;
220   m = n->message_head;
221   if (NULL == m)
222   {
223     GNUNET_break (0);
224     return 0;
225   }
226   GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
227   if (NULL == buf)
228   {
229     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
230                 "Transmission of message of type %u and size %u failed\n",
231                 (unsigned int)
232                 ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
233                 (unsigned int) m->size);
234     GNUNET_free (m);
235     process_queue (n);
236     return 0;
237   }
238   cbuf = buf;
239   GNUNET_assert (size >= m->size);
240   memcpy (cbuf, &m[1], m->size);
241   ret = m->size;
242   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
243               "Copied message of type %u and size %u into transport buffer for `%4s'\n",
244               (unsigned int)
245               ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
246               (unsigned int) ret, GNUNET_i2s (&n->peer));
247   GNUNET_free (m);
248   n->has_excess_bandwidth = GNUNET_NO;
249   process_queue (n);
250   GNUNET_STATISTICS_update (GSC_stats,
251                             gettext_noop
252                             ("# encrypted bytes given to transport"), ret,
253                             GNUNET_NO);
254   return ret;
255 }
256
257
258 /**
259  * Check if we have messages for the specified neighbour pending, and
260  * if so, check with the transport about sending them out.
261  *
262  * @param n neighbour to check.
263  */
264 static void
265 process_queue (struct Neighbour *n)
266 {
267   struct NeighbourMessageEntry *m;
268
269   if (NULL != n->th)
270     return;                     /* request already pending */
271   m = n->message_head;
272   if (NULL == m)
273   {
274     /* notify sessions that the queue is empty and more messages
275      * could thus be queued now */
276     GSC_SESSIONS_solicit (&n->peer);
277     return;
278   }
279   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280               "Asking transport for transmission of %u bytes to `%4s' in next %s\n",
281               (unsigned int) m->size,
282               GNUNET_i2s (&n->peer),
283               GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (m->deadline),
284                                                       GNUNET_NO));
285   n->th
286     = GNUNET_TRANSPORT_notify_transmit_ready (transport,
287                                               &n->peer,
288                                               m->size,
289                                               GNUNET_TIME_absolute_get_remaining (m->deadline),
290                                               &transmit_ready,
291                                               n);
292   if (NULL != n->th)
293     return;
294   /* message request too large or duplicate request */
295   GNUNET_break (0);
296   /* discard encrypted message */
297   GNUNET_CONTAINER_DLL_remove (n->message_head,
298                                n->message_tail,
299                                m);
300   GNUNET_free (m);
301   process_queue (n);
302 }
303
304
305 /**
306  * Function called by transport to notify us that
307  * a peer connected to us (on the network level).
308  *
309  * @param cls closure
310  * @param peer the peer that connected
311  */
312 static void
313 handle_transport_notify_connect (void *cls,
314                                  const struct GNUNET_PeerIdentity *peer)
315 {
316   struct Neighbour *n;
317
318   if (0 == memcmp (peer,
319                    &GSC_my_identity,
320                    sizeof (struct GNUNET_PeerIdentity)))
321   {
322     GNUNET_break (0);
323     return;
324   }
325   n = find_neighbour (peer);
326   if (n != NULL)
327   {
328     /* duplicate connect notification!? */
329     GNUNET_break (0);
330     return;
331   }
332   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333               "Received connection from `%4s'.\n",
334               GNUNET_i2s (peer));
335   n = GNUNET_new (struct Neighbour);
336   n->peer = *peer;
337   GNUNET_assert (GNUNET_OK ==
338                  GNUNET_CONTAINER_multipeermap_put (neighbours,
339                                                     &n->peer, n,
340                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
341   GNUNET_STATISTICS_set (GSC_stats,
342                          gettext_noop ("# neighbour entries allocated"),
343                          GNUNET_CONTAINER_multipeermap_size (neighbours),
344                          GNUNET_NO);
345   n->kxinfo = GSC_KX_start (peer);
346 }
347
348
349 /**
350  * Function called by transport telling us that a peer
351  * disconnected.
352  *
353  * @param cls closure
354  * @param peer the peer that disconnected
355  */
356 static void
357 handle_transport_notify_disconnect (void *cls,
358                                     const struct GNUNET_PeerIdentity *peer)
359 {
360   struct Neighbour *n;
361
362   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
363               "Peer `%4s' disconnected from us; received notification from transport.\n",
364               GNUNET_i2s (peer));
365   n = find_neighbour (peer);
366   if (NULL == n)
367   {
368     GNUNET_break (0);
369     return;
370   }
371   free_neighbour (n);
372 }
373
374
375 /**
376  * Function called by the transport for each received message.
377  *
378  * @param cls closure
379  * @param peer (claimed) identity of the other peer
380  * @param message the message
381  */
382 static void
383 handle_transport_receive (void *cls,
384                           const struct GNUNET_PeerIdentity *peer,
385                           const struct GNUNET_MessageHeader *message)
386 {
387   struct Neighbour *n;
388   uint16_t type;
389
390   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391               "Received message of type %u from `%4s', demultiplexing.\n",
392               (unsigned int) ntohs (message->type), GNUNET_i2s (peer));
393   if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
394   {
395     GNUNET_break (0);
396     return;
397   }
398   n = find_neighbour (peer);
399   if (n == NULL)
400   {
401     /* received message from peer that is not connected!? */
402     GNUNET_break (0);
403     return;
404   }
405   type = ntohs (message->type);
406   switch (type)
407   {
408   case GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY:
409     GSC_KX_handle_ephemeral_key (n->kxinfo, message);
410     break;
411   case GNUNET_MESSAGE_TYPE_CORE_PING:
412     GSC_KX_handle_ping (n->kxinfo, message);
413     break;
414   case GNUNET_MESSAGE_TYPE_CORE_PONG:
415     GSC_KX_handle_pong (n->kxinfo, message);
416     break;
417   case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
418     GSC_KX_handle_encrypted_message (n->kxinfo, message);
419     break;
420   case GNUNET_MESSAGE_TYPE_DUMMY:
421     /*  Dummy messages for testing / benchmarking, just discard */
422     break;
423   default:
424     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
425                 _("Unsupported message of type %u (%u bytes) received from peer `%s'\n"),
426                 (unsigned int) type,
427                 (unsigned int) ntohs (message->size),
428                 GNUNET_i2s (peer));
429     return;
430   }
431 }
432
433
434 /**
435  * Transmit the given message to the given target.
436  *
437  * @param target peer that should receive the message (must be connected)
438  * @param msg message to transmit
439  * @param timeout by when should the transmission be done?
440  */
441 void
442 GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
443                          const struct GNUNET_MessageHeader *msg,
444                          struct GNUNET_TIME_Relative timeout)
445 {
446   struct NeighbourMessageEntry *me;
447   struct Neighbour *n;
448   size_t msize;
449
450   n = find_neighbour (target);
451   if (NULL == n)
452   {
453     GNUNET_break (0);
454     return;
455   }
456   msize = ntohs (msg->size);
457   me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize);
458   me->deadline = GNUNET_TIME_relative_to_absolute (timeout);
459   me->size = msize;
460   memcpy (&me[1], msg, msize);
461   GNUNET_CONTAINER_DLL_insert_tail (n->message_head, n->message_tail, me);
462   process_queue (n);
463 }
464
465
466 /**
467  * One of our neighbours has excess bandwidth,
468  * remember this.
469  *
470  * @param cls NULL
471  * @param pid identity of the peer with excess bandwidth
472  */
473 static void
474 handle_transport_notify_excess_bw (void *cls,
475                                    const struct GNUNET_PeerIdentity *pid)
476 {
477   struct Neighbour *n;
478
479   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
480               "Peer %s has excess bandwidth available\n",
481               GNUNET_i2s (pid));
482   n = find_neighbour (pid);
483   if (NULL == n)
484   {
485     GNUNET_break (0);
486     return;
487   }
488   n->has_excess_bandwidth = GNUNET_YES;
489   GSC_SESSIONS_solicit (pid);
490 }
491
492
493 /**
494  * Check if the given neighbour has excess bandwidth available.
495  *
496  * @param target neighbour to check
497  * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
498  */
499 int
500 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GNUNET_PeerIdentity *target)
501 {
502   struct Neighbour *n;
503
504   n = find_neighbour (target);
505   if (NULL == n)
506   {
507     GNUNET_break (0);
508     return GNUNET_SYSERR;
509   }
510   return n->has_excess_bandwidth;
511 }
512
513
514 /**
515  * Initialize neighbours subsystem.
516  */
517 int
518 GSC_NEIGHBOURS_init ()
519 {
520   neighbours = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
521   transport =
522       GNUNET_TRANSPORT_connect2 (GSC_cfg, &GSC_my_identity, NULL,
523                                  &handle_transport_receive,
524                                  &handle_transport_notify_connect,
525                                  &handle_transport_notify_disconnect,
526                                  &handle_transport_notify_excess_bw);
527   if (NULL == transport)
528   {
529     GNUNET_CONTAINER_multipeermap_destroy (neighbours);
530     neighbours = NULL;
531     return GNUNET_SYSERR;
532   }
533   return GNUNET_OK;
534 }
535
536
537 /**
538  * Wrapper around 'free_neighbour'.
539  *
540  * @param cls unused
541  * @param key peer identity
542  * @param value the `struct Neighbour` to free
543  * @return #GNUNET_OK (continue to iterate)
544  */
545 static int
546 free_neighbour_helper (void *cls,
547                        const struct GNUNET_PeerIdentity * key,
548                        void *value)
549 {
550   struct Neighbour *n = value;
551
552   /* transport should have 'disconnected' all neighbours... */
553   GNUNET_break (0);
554   free_neighbour (n);
555   return GNUNET_OK;
556 }
557
558
559 /**
560  * Shutdown neighbours subsystem.
561  */
562 void
563 GSC_NEIGHBOURS_done ()
564 {
565   if (NULL != transport)
566   {
567     GNUNET_TRANSPORT_disconnect (transport);
568     transport = NULL;
569   }
570   if (NULL != neighbours)
571   {
572     GNUNET_CONTAINER_multipeermap_iterate (neighbours,
573                                            &free_neighbour_helper,
574                                            NULL);
575     GNUNET_CONTAINER_multipeermap_destroy (neighbours);
576     neighbours = NULL;
577   }
578 }
579
580 /* end of gnunet-service-core_neighbours.c */