Don't pass NULL to destroy_route
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_core.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2017 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file cadet/gnunet-service-cadet_core.c
23  * @brief cadet service; interaction with CORE service
24  * @author Bartlomiej Polot
25  * @author Christian Grothoff
26  *
27  * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28  *
29  * TODO:
30  * - properly implement GLOBAL message buffer, instead of per-route buffers
31  * - do NOT use buffering if the route options say no buffer!
32  * - Optimization: given BROKEN messages, destroy paths (?)
33  */
34 #include "platform.h"
35 #include "gnunet-service-cadet-new_core.h"
36 #include "gnunet-service-cadet-new_paths.h"
37 #include "gnunet-service-cadet-new_peer.h"
38 #include "gnunet-service-cadet-new_connection.h"
39 #include "gnunet-service-cadet-new_tunnels.h"
40 #include "gnunet_core_service.h"
41 #include "gnunet_statistics_service.h"
42 #include "cadet_protocol.h"
43
44
45 #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__)
46
47
48 /**
49  * Number of messages we are willing to buffer per route.
50  * FIXME: have global buffer pool instead!
51  */
52 #define ROUTE_BUFFER_SIZE 8
53
54
55 /**
56  * Information we keep per direction for a route.
57  */
58 struct RouteDirection
59 {
60   /**
61    * Target peer.
62    */
63   struct CadetPeer *hop;
64
65   /**
66    * Route this direction is part of.
67    */
68   struct CadetRoute *my_route;
69
70   /**
71    * Message queue manager for @e hop.
72    */
73   struct GCP_MessageQueueManager *mqm;
74
75   /**
76    * Cyclic message buffer to @e hop.
77    */
78   struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
79
80   /**
81    * Next write offset to use to append messages to @e out_buffer.
82    */
83   unsigned int out_wpos;
84
85   /**
86    * Next read offset to use to retrieve messages from @e out_buffer.
87    */
88   unsigned int out_rpos;
89
90   /**
91    * Is @e mqm currently ready for transmission?
92    */
93   int is_ready;
94
95 };
96
97
98 /**
99  * Description of a segment of a `struct CadetConnection` at the
100  * intermediate peers.  Routes are basically entries in a peer's
101  * routing table for forwarding traffic.  At both endpoints, the
102  * routes are terminated by a `struct CadetConnection`, which knows
103  * the complete `struct CadetPath` that is formed by the individual
104  * routes.
105  */
106 struct CadetRoute
107 {
108
109   /**
110    * Information about the next hop on this route.
111    */
112   struct RouteDirection next;
113
114   /**
115    * Information about the previous hop on this route.
116    */
117   struct RouteDirection prev;
118
119   /**
120    * Unique identifier for the connection that uses this route.
121    */
122   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
123
124   /**
125    * When was this route last in use?
126    */
127   struct GNUNET_TIME_Absolute last_use;
128
129   /**
130    * Position of this route in the #route_heap.
131    */
132   struct GNUNET_CONTAINER_HeapNode *hn;
133
134   /**
135    * Options for the route, control buffering.
136    */
137   enum GNUNET_CADET_ChannelOption options;
138 };
139
140
141 /**
142  * Handle to the CORE service.
143  */
144 static struct GNUNET_CORE_Handle *core;
145
146 /**
147  * Routes on which this peer is an intermediate.
148  */
149 static struct GNUNET_CONTAINER_MultiShortmap *routes;
150
151 /**
152  * Heap of routes, MIN-sorted by last activity.
153  */
154 static struct GNUNET_CONTAINER_Heap *route_heap;
155
156 /**
157  * Maximum number of concurrent routes this peer will support.
158  */
159 static unsigned long long max_routes;
160
161 /**
162  * Task to timeout routes.
163  */
164 static struct GNUNET_SCHEDULER_Task *timeout_task;
165
166
167 /**
168  * Get the route corresponding to a hash.
169  *
170  * @param cid hash generated from the connection identifier
171  */
172 static struct CadetRoute *
173 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
174 {
175   return GNUNET_CONTAINER_multishortmap_get (routes,
176                                              &cid->connection_of_tunnel);
177 }
178
179
180 /**
181  * We message @a msg from @a prev.  Find its route by @a cid and
182  * forward to the next hop.  Drop and signal broken route if we do not
183  * have a route.
184  *
185  * @param prev previous hop (sender)
186  * @param cid connection identifier, tells us which route to use
187  * @param msg the message to forward
188  */
189 static void
190 route_message (struct CadetPeer *prev,
191                const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
192                const struct GNUNET_MessageHeader *msg)
193 {
194   struct CadetRoute *route;
195   struct RouteDirection *dir;
196   struct GNUNET_MQ_Envelope *env;
197
198   route = get_route (cid);
199   if (NULL == route)
200   {
201     struct GNUNET_MQ_Envelope *env;
202     struct GNUNET_CADET_ConnectionBrokenMessage *bm;
203
204     LOG (GNUNET_ERROR_TYPE_DEBUG,
205          "Failed to route message of type %u from %s on connection %s: no route\n",
206          ntohs (msg->type),
207          GCP_2s (prev),
208          GNUNET_sh2s (&cid->connection_of_tunnel));
209     env = GNUNET_MQ_msg (bm,
210                          GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
211     bm->cid = *cid;
212     bm->peer1 = my_full_id;
213     GCP_send_ooo (prev,
214                   env);
215     return;
216   }
217   route->last_use = GNUNET_TIME_absolute_get ();
218   GNUNET_CONTAINER_heap_update_cost (route->hn,
219                                      route->last_use.abs_value_us);
220   dir = (prev == route->prev.hop) ? &route->next : &route->prev;
221   if (GNUNET_YES == dir->is_ready)
222   {
223     LOG (GNUNET_ERROR_TYPE_DEBUG,
224          "Routing message of type %u from %s to %s on connection %s\n",
225          ntohs (msg->type),
226          GCP_2s (prev),
227          GNUNET_i2s (GCP_get_id (dir->hop)),
228          GNUNET_sh2s (&cid->connection_of_tunnel));
229     dir->is_ready = GNUNET_NO;
230     GCP_send (dir->mqm,
231               GNUNET_MQ_msg_copy (msg));
232     return;
233   }
234   env = dir->out_buffer[dir->out_wpos];
235   if (NULL != env)
236   {
237     /* Queue full, drop earliest message in queue */
238     LOG (GNUNET_ERROR_TYPE_DEBUG,
239          "Queue full due to new message of type %u from %s to %s on connection %s, dropping old message\n",
240          ntohs (msg->type),
241          GCP_2s (prev),
242          GNUNET_i2s (GCP_get_id (dir->hop)),
243          GNUNET_sh2s (&cid->connection_of_tunnel));
244     GNUNET_STATISTICS_update (stats,
245                               "# messages dropped due to full buffer",
246                               1,
247                               GNUNET_NO);
248   GNUNET_assert (dir->out_rpos == dir->out_wpos);
249     GNUNET_MQ_discard (env);
250     dir->out_rpos++;
251     if (ROUTE_BUFFER_SIZE == dir->out_rpos)
252       dir->out_rpos = 0;
253   }
254   LOG (GNUNET_ERROR_TYPE_DEBUG,
255        "Queueing new message of type %u from %s to %s on connection %s\n",
256        ntohs (msg->type),
257        GCP_2s (prev),
258        GNUNET_i2s (GCP_get_id (dir->hop)),
259        GNUNET_sh2s (&cid->connection_of_tunnel));
260   env = GNUNET_MQ_msg_copy (msg);
261   dir->out_buffer[dir->out_wpos] = env;
262   dir->out_wpos++;
263   if (ROUTE_BUFFER_SIZE == dir->out_wpos)
264     dir->out_wpos = 0;
265 }
266
267
268 /**
269  * Check if the create_connection message has the appropriate size.
270  *
271  * @param cls Closure (unused).
272  * @param msg Message to check.
273  *
274  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
275  */
276 static int
277 check_connection_create (void *cls,
278                          const struct GNUNET_CADET_ConnectionCreateMessage *msg)
279 {
280   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
281
282   if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
283   {
284     GNUNET_break_op (0);
285     return GNUNET_NO;
286   }
287   return GNUNET_YES;
288 }
289
290
291 /**
292  * Free internal data of a route direction.
293  *
294  * @param dir direction to destroy (do NOT free memory of 'dir' itself)
295  */
296 static void
297 destroy_direction (struct RouteDirection *dir)
298 {
299   for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
300     if (NULL != dir->out_buffer[i])
301     {
302       GNUNET_MQ_discard (dir->out_buffer[i]);
303       dir->out_buffer[i] = NULL;
304     }
305   if (NULL != dir->mqm)
306   {
307     GCP_request_mq_cancel (dir->mqm,
308                            NULL);
309     dir->mqm = NULL;
310   }
311 }
312
313
314 /**
315  * Destroy our state for @a route.
316  *
317  * @param route route to destroy
318  */
319 static void
320 destroy_route (struct CadetRoute *route)
321 {
322   LOG (GNUNET_ERROR_TYPE_DEBUG,
323        "Destroying route from %s to %s of connection %s\n",
324        GNUNET_i2s  (GCP_get_id (route->prev.hop)),
325        GNUNET_i2s2 (GCP_get_id (route->next.hop)),
326        GNUNET_sh2s (&route->cid.connection_of_tunnel));
327   GNUNET_assert (route ==
328                  GNUNET_CONTAINER_heap_remove_node (route->hn));
329   GNUNET_assert (GNUNET_YES ==
330                  GNUNET_CONTAINER_multishortmap_remove (routes,
331                                                         &route->cid.connection_of_tunnel,
332                                                         route));
333   destroy_direction (&route->prev);
334   destroy_direction (&route->next);
335   GNUNET_free (route);
336 }
337
338
339 /**
340  * Send message that a route is broken between @a peer1 and @a peer2.
341  *
342  * @param target where to send the message
343  * @param cid connection identifier to use
344  * @param peer1 one of the peers where a link is broken
345  * @param peer2 another one of the peers where a link is broken
346  */
347 static void
348 send_broken (struct RouteDirection *target,
349              const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
350              const struct GNUNET_PeerIdentity *peer1,
351              const struct GNUNET_PeerIdentity *peer2)
352 {
353   struct GNUNET_MQ_Envelope *env;
354   struct GNUNET_CADET_ConnectionBrokenMessage *bm;
355
356   if (NULL == target->mqm)
357     return; /* Can't send notification, connection is down! */
358   LOG (GNUNET_ERROR_TYPE_DEBUG,
359        "Notifying %s about BROKEN route at %s-%s of connection %s\n",
360        GCP_2s (target->hop),
361        GNUNET_i2s (peer1),
362        GNUNET_i2s2 (peer2),
363        GNUNET_sh2s (&cid->connection_of_tunnel));
364
365   env = GNUNET_MQ_msg (bm,
366                        GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
367   bm->cid = *cid;
368   if (NULL != peer1)
369     bm->peer1 = *peer1;
370   if (NULL != peer2)
371     bm->peer2 = *peer2;
372
373   GCP_request_mq_cancel (target->mqm,
374                          env);
375   target->mqm = NULL;
376 }
377
378
379 /**
380  * Function called to check if any routes have timed out, and if
381  * so, to clean them up.  Finally, schedules itself again at the
382  * earliest time where there might be more work.
383  *
384  * @param cls NULL
385  */
386 static void
387 timeout_cb (void *cls)
388 {
389   struct CadetRoute *r;
390   struct GNUNET_TIME_Relative linger;
391   struct GNUNET_TIME_Absolute exp;
392
393   timeout_task = NULL;
394   linger = GNUNET_TIME_relative_multiply (keepalive_period,
395                                           3);
396   while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
397   {
398     exp = GNUNET_TIME_absolute_add (r->last_use,
399                                     linger);
400     if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
401     {
402       /* Route not yet timed out, wait until it does. */
403       timeout_task = GNUNET_SCHEDULER_add_at (exp,
404                                               &timeout_cb,
405                                               NULL);
406       return;
407     }
408     send_broken (&r->prev,
409                  &r->cid,
410                  NULL,
411                  NULL);
412     send_broken (&r->next,
413                  &r->cid,
414                  NULL,
415                  NULL);
416     destroy_route (r);
417   }
418   /* No more routes left, so no need for a #timeout_task */
419 }
420
421
422 /**
423  * Function called when the message queue to the previous hop
424  * becomes available/unavailable.  We expect this function to
425  * be called immediately when we register, and then again
426  * later if the connection ever goes down.
427  *
428  * @param cls the `struct RouteDirection`
429  * @param available #GNUNET_YES if sending is now possible,
430  *                  #GNUNET_NO if sending is no longer possible
431  *                  #GNUNET_SYSERR if sending is no longer possible
432  *                                 and the last envelope was discarded
433  */
434 static void
435 dir_ready_cb (void *cls,
436               int ready)
437 {
438   struct RouteDirection *dir = cls;
439   struct CadetRoute *route = dir->my_route;
440   struct RouteDirection *odir;
441
442   if (GNUNET_YES == ready)
443   {
444     struct GNUNET_MQ_Envelope *env;
445
446     dir->is_ready = GNUNET_YES;
447     if (NULL != (env = dir->out_buffer[dir->out_rpos]))
448     {
449       dir->out_buffer[dir->out_rpos] = NULL;
450       dir->out_rpos++;
451       if (ROUTE_BUFFER_SIZE == dir->out_rpos)
452         dir->out_rpos = 0;
453       dir->is_ready = GNUNET_NO;
454       GCP_send (dir->mqm,
455                 env);
456     }
457     return;
458   }
459   odir = (dir == &route->next) ? &route->prev : &route->next;
460   send_broken (&route->next,
461                &route->cid,
462                GCP_get_id (odir->hop),
463                &my_full_id);
464   destroy_route (route);
465 }
466
467
468 /**
469  * Initialize one of the directions of a route.
470  *
471  * @param route route the direction belongs to
472  * @param dir direction to initialize
473  * @param hop next hop on in the @a dir
474  */
475 static void
476 dir_init (struct RouteDirection *dir,
477           struct CadetRoute *route,
478           struct CadetPeer *hop)
479 {
480   dir->hop = hop;
481   dir->my_route = route;
482   dir->mqm = GCP_request_mq (hop,
483                              &dir_ready_cb,
484                              dir);
485   GNUNET_assert (GNUNET_YES == dir->is_ready);
486 }
487
488
489 /**
490  * We could not create the desired route.  Send a
491  * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
492  * message to @a target.
493  *
494  * @param target who should receive the message
495  * @param cid identifier of the connection/route that failed
496  * @param failure_at neighbour with which we failed to route,
497  *        or NULL.
498  */
499 static void
500 send_broken_without_mqm (struct CadetPeer *target,
501                          const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
502                          const struct GNUNET_PeerIdentity *failure_at)
503 {
504   struct GNUNET_MQ_Envelope *env;
505   struct GNUNET_CADET_ConnectionBrokenMessage *bm;
506
507   env = GNUNET_MQ_msg (bm,
508                        GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
509   bm->cid = *cid;
510   bm->peer1 = my_full_id;
511   if (NULL != failure_at)
512     bm->peer2 = *failure_at;
513   GCP_send_ooo (target,
514                 env);
515 }
516
517
518 /**
519  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
520  *
521  * @param cls Closure (CadetPeer for neighbor that sent the message).
522  * @param msg Message itself.
523  */
524 static void
525 handle_connection_create (void *cls,
526                           const struct GNUNET_CADET_ConnectionCreateMessage *msg)
527 {
528   struct CadetPeer *sender = cls;
529   struct CadetPeer *next;
530   const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
531   struct CadetRoute *route;
532   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
533   unsigned int path_length;
534   unsigned int off;
535   enum GNUNET_CADET_ChannelOption options;
536
537   options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
538   path_length = size / sizeof (struct GNUNET_PeerIdentity);
539   /* Initiator is at offset 0. */
540   for (off=1;off<path_length;off++)
541     if (0 == memcmp (&my_full_id,
542                      &pids[off],
543                      sizeof (struct GNUNET_PeerIdentity)))
544       break;
545   if (off == path_length)
546   {
547     /* We are not on the path, bogus request */
548     GNUNET_break_op (0);
549     return;
550   }
551   /* Check previous hop */
552   if (sender != GCP_get (&pids[off - 1],
553                          GNUNET_NO))
554   {
555     /* sender is not on the path, not allowed */
556     GNUNET_break_op (0);
557     return;
558   }
559   if (NULL !=
560       get_route (&msg->cid))
561   {
562     /* Duplicate CREATE, pass it on, previous one might have been lost! */
563     LOG (GNUNET_ERROR_TYPE_DEBUG,
564          "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
565          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
566     route_message (sender,
567                    &msg->cid,
568                    &msg->header);
569     return;
570   }
571   if (off == path_length - 1)
572   {
573     /* We are the destination, create connection */
574     struct CadetConnection *cc;
575     struct CadetPeerPath *path;
576     struct CadetPeer *origin;
577
578     cc = GNUNET_CONTAINER_multishortmap_get (connections,
579                                              &msg->cid.connection_of_tunnel);
580     if (NULL != cc)
581     {
582       LOG (GNUNET_ERROR_TYPE_DEBUG,
583            "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
584            GNUNET_sh2s (&msg->cid.connection_of_tunnel));
585       GCC_handle_duplicate_create (cc);
586       return;
587     }
588
589     origin = GCP_get (&pids[0],
590                       GNUNET_YES);
591     LOG (GNUNET_ERROR_TYPE_DEBUG,
592          "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
593          GCP_2s (origin),
594          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
595     path = GCPP_get_path_from_route (path_length - 1,
596                                      pids);
597     if (GNUNET_OK !=
598         GCT_add_inbound_connection (GCP_get_tunnel (origin,
599                                                     GNUNET_YES),
600                                     &msg->cid,
601                                     (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
602                                     path))
603     {
604       /* Send back BROKEN: duplicate connection on the same path,
605          we will use the other one. */
606       LOG (GNUNET_ERROR_TYPE_DEBUG,
607            "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
608            GCP_2s (sender),
609            GNUNET_sh2s (&msg->cid.connection_of_tunnel),
610            GCPP_2s (path));
611       send_broken_without_mqm (sender,
612                                &msg->cid,
613                                NULL);
614       return;
615     }
616     return;
617   }
618   /* We are merely a hop on the way, check if we can support the route */
619   next = GCP_get (&pids[off + 1],
620                   GNUNET_NO);
621   if ( (NULL == next) ||
622        (GNUNET_NO == GCP_has_core_connection (next)) )
623   {
624     /* unworkable, send back BROKEN notification */
625     LOG (GNUNET_ERROR_TYPE_DEBUG,
626          "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
627          GCP_2s (sender),
628          GNUNET_sh2s (&msg->cid.connection_of_tunnel),
629          GNUNET_i2s (&pids[off + 1]),
630          off + 1);
631     send_broken_without_mqm (sender,
632                              &msg->cid,
633                              &pids[off + 1]);
634     return;
635   }
636   if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
637   {
638     LOG (GNUNET_ERROR_TYPE_DEBUG,
639          "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
640          GCP_2s (sender),
641          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
642     send_broken_without_mqm (sender,
643                              &msg->cid,
644                              &pids[off - 1]);
645     return;
646   }
647
648   /* Workable route, create routing entry */
649   LOG (GNUNET_ERROR_TYPE_DEBUG,
650        "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
651        GCP_2s (sender),
652        GNUNET_sh2s (&msg->cid.connection_of_tunnel),
653        GNUNET_i2s (&pids[off + 1]),
654        off + 1);
655   route = GNUNET_new (struct CadetRoute);
656   route->options = options;
657   route->cid = msg->cid;
658   route->last_use = GNUNET_TIME_absolute_get ();
659   dir_init (&route->prev,
660             route,
661             sender);
662   dir_init (&route->next,
663             route,
664             next);
665   GNUNET_assert (GNUNET_OK ==
666                  GNUNET_CONTAINER_multishortmap_put (routes,
667                                                      &route->cid.connection_of_tunnel,
668                                                      route,
669                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
670   route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
671                                             route,
672                                             route->last_use.abs_value_us);
673   if (NULL == timeout_task)
674     timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
675                                                                                 3),
676                                                  &timeout_cb,
677                                                  NULL);
678 }
679
680
681 /**
682  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
683  *
684  * @param cls Closure (CadetPeer for neighbor that sent the message).
685  * @param msg Message itself.
686  */
687 static void
688 handle_connection_create_ack (void *cls,
689                               const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
690 {
691   struct CadetPeer *peer = cls;
692   struct CadetConnection *cc;
693
694   /* First, check if ACK belongs to a connection that ends here. */
695   cc = GNUNET_CONTAINER_multishortmap_get (connections,
696                                            &msg->cid.connection_of_tunnel);
697   if (NULL != cc)
698   {
699     /* verify ACK came from the right direction */
700     struct CadetPeerPath *path = GCC_get_path (cc);
701
702     if (peer !=
703         GCPP_get_peer_at_offset (path,
704                                  0))
705     {
706       /* received ACK from unexpected direction, ignore! */
707       GNUNET_break_op (0);
708       return;
709     }
710     LOG (GNUNET_ERROR_TYPE_DEBUG,
711          "Received CONNECTION_CREATE_ACK for connection %s.\n",
712          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
713     GCC_handle_connection_create_ack (cc);
714     return;
715   }
716
717   /* We're just an intermediary peer, route the message along its path */
718   route_message (peer,
719                  &msg->cid,
720                  &msg->header);
721 }
722
723
724 /**
725  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
726  *
727  * @param cls Closure (CadetPeer for neighbor that sent the message).
728  * @param msg Message itself.
729  * @deprecated duplicate logic with #handle_destroy(); dedup!
730  */
731 static void
732 handle_connection_broken (void *cls,
733                           const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
734 {
735   struct CadetPeer *peer = cls;
736   struct CadetConnection *cc;
737   struct CadetRoute *route;
738
739   /* First, check if message belongs to a connection that ends here. */
740   cc = GNUNET_CONTAINER_multishortmap_get (connections,
741                                            &msg->cid.connection_of_tunnel);
742   if (NULL != cc)
743   {
744     /* verify message came from the right direction */
745     struct CadetPeerPath *path = GCC_get_path (cc);
746
747     if (peer !=
748         GCPP_get_peer_at_offset (path,
749                                  0))
750     {
751       /* received message from unexpected direction, ignore! */
752       GNUNET_break_op (0);
753       return;
754     }
755     LOG (GNUNET_ERROR_TYPE_DEBUG,
756          "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
757          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
758     GCC_destroy_without_core (cc);
759
760     /* FIXME: also destroy the path up to the specified link! */
761     return;
762   }
763
764   /* We're just an intermediary peer, route the message along its path */
765   route_message (peer,
766                  &msg->cid,
767                  &msg->header);
768   route = get_route (&msg->cid);
769   if (NULL != route)
770     destroy_route (route);
771   /* FIXME: also destroy paths we MAY have up to the specified link! */
772 }
773
774
775 /**
776  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
777  *
778  * @param cls Closure (CadetPeer for neighbor that sent the message).
779  * @param msg Message itself.
780  */
781 static void
782 handle_connection_destroy (void *cls,
783                            const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
784 {
785   struct CadetPeer *peer = cls;
786   struct CadetConnection *cc;
787   struct CadetRoute *route;
788
789   /* First, check if message belongs to a connection that ends here. */
790   cc = GNUNET_CONTAINER_multishortmap_get (connections,
791                                            &msg->cid.connection_of_tunnel);
792   if (NULL != cc)
793   {
794     /* verify message came from the right direction */
795     struct CadetPeerPath *path = GCC_get_path (cc);
796
797     if (peer !=
798         GCPP_get_peer_at_offset (path,
799                                  0))
800     {
801       /* received message from unexpected direction, ignore! */
802       GNUNET_break_op (0);
803       return;
804     }
805     LOG (GNUNET_ERROR_TYPE_DEBUG,
806          "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
807          GNUNET_sh2s (&msg->cid.connection_of_tunnel));
808
809     GCC_destroy_without_core (cc);
810     return;
811   }
812
813   /* We're just an intermediary peer, route the message along its path */
814   LOG (GNUNET_ERROR_TYPE_DEBUG,
815        "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
816        GNUNET_sh2s (&msg->cid.connection_of_tunnel));
817   route_message (peer,
818                  &msg->cid,
819                  &msg->header);
820   route = get_route (&msg->cid);
821   if (NULL != route)
822     destroy_route (route);
823 }
824
825
826 /**
827  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
828  *
829  * @param cls Closure (CadetPeer for neighbor that sent the message).
830  * @param msg Message itself.
831  */
832 static void
833 handle_tunnel_kx (void *cls,
834                   const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
835 {
836   struct CadetPeer *peer = cls;
837   struct CadetConnection *cc;
838
839   /* First, check if message belongs to a connection that ends here. */
840   cc = GNUNET_CONTAINER_multishortmap_get (connections,
841                                            &msg->cid.connection_of_tunnel);
842   if (NULL != cc)
843   {
844     /* verify message came from the right direction */
845     struct CadetPeerPath *path = GCC_get_path (cc);
846
847     if (peer !=
848         GCPP_get_peer_at_offset (path,
849                                  0))
850     {
851       /* received message from unexpected direction, ignore! */
852       GNUNET_break_op (0);
853       return;
854     }
855     GCC_handle_kx (cc,
856                    msg);
857     return;
858   }
859
860   /* We're just an intermediary peer, route the message along its path */
861   route_message (peer,
862                  &msg->cid,
863                  &msg->header);
864 }
865
866
867 /**
868  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
869  *
870  * @param cls Closure (CadetPeer for neighbor that sent the message).
871  * @param msg Message itself.
872  */
873 static void
874 handle_tunnel_kx_auth (void *cls,
875                        const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
876 {
877   struct CadetPeer *peer = cls;
878   struct CadetConnection *cc;
879
880   /* First, check if message belongs to a connection that ends here. */
881   cc = GNUNET_CONTAINER_multishortmap_get (connections,
882                                            &msg->kx.cid.connection_of_tunnel);
883   if (NULL != cc)
884   {
885     /* verify message came from the right direction */
886     struct CadetPeerPath *path = GCC_get_path (cc);
887
888     if (peer !=
889         GCPP_get_peer_at_offset (path,
890                                  0))
891     {
892       /* received message from unexpected direction, ignore! */
893       GNUNET_break_op (0);
894       return;
895     }
896     GCC_handle_kx_auth (cc,
897                         msg);
898     return;
899   }
900
901   /* We're just an intermediary peer, route the message along its path */
902   route_message (peer,
903                  &msg->kx.cid,
904                  &msg->kx.header);
905 }
906
907
908 /**
909  * Check if the encrypted message has the appropriate size.
910  *
911  * @param cls Closure (unused).
912  * @param msg Message to check.
913  *
914  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
915  */
916 static int
917 check_tunnel_encrypted (void *cls,
918                         const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
919 {
920   return GNUNET_YES;
921 }
922
923
924 /**
925  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
926  *
927  * @param cls Closure (CadetPeer for neighbor that sent the message).
928  * @param msg Message itself.
929  */
930 static void
931 handle_tunnel_encrypted (void *cls,
932                          const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
933 {
934   struct CadetPeer *peer = cls;
935   struct CadetConnection *cc;
936
937   /* First, check if message belongs to a connection that ends here. */
938   cc = GNUNET_CONTAINER_multishortmap_get (connections,
939                                            &msg->cid.connection_of_tunnel);
940   if (NULL != cc)
941   {
942     /* verify message came from the right direction */
943     struct CadetPeerPath *path = GCC_get_path (cc);
944
945     if (peer !=
946         GCPP_get_peer_at_offset (path,
947                                  0))
948     {
949       /* received message from unexpected direction, ignore! */
950       GNUNET_break_op (0);
951       return;
952     }
953     GCC_handle_encrypted (cc,
954                           msg);
955     return;
956   }
957   /* We're just an intermediary peer, route the message along its path */
958   route_message (peer,
959                  &msg->cid,
960                  &msg->header);
961 }
962
963
964 /**
965  * Function called after #GNUNET_CORE_connect has succeeded (or failed
966  * for good).  Note that the private key of the peer is intentionally
967  * not exposed here; if you need it, your process should try to read
968  * the private key file directly (which should work if you are
969  * authorized...).  Implementations of this function must not call
970  * #GNUNET_CORE_disconnect (other than by scheduling a new task to
971  * do this later).
972  *
973  * @param cls closure
974  * @param my_identity ID of this peer, NULL if we failed
975  */
976 static void
977 core_init_cb (void *cls,
978               const struct GNUNET_PeerIdentity *my_identity)
979 {
980   if (NULL == my_identity)
981   {
982     GNUNET_break (0);
983     return;
984   }
985   GNUNET_break (0 ==
986                 memcmp (my_identity,
987                         &my_full_id,
988                         sizeof (struct GNUNET_PeerIdentity)));
989 }
990
991
992 /**
993  * Method called whenever a given peer connects.
994  *
995  * @param cls closure
996  * @param peer peer identity this notification is about
997  */
998 static void *
999 core_connect_cb (void *cls,
1000                  const struct GNUNET_PeerIdentity *peer,
1001                  struct GNUNET_MQ_Handle *mq)
1002 {
1003   struct CadetPeer *cp;
1004
1005   LOG (GNUNET_ERROR_TYPE_DEBUG,
1006        "CORE connection to peer %s was established.\n",
1007        GNUNET_i2s (peer));
1008   cp = GCP_get (peer,
1009                 GNUNET_YES);
1010   GCP_set_mq (cp,
1011               mq);
1012   return cp;
1013 }
1014
1015
1016 /**
1017  * Method called whenever a peer disconnects.
1018  *
1019  * @param cls closure
1020  * @param peer peer identity this notification is about
1021  */
1022 static void
1023 core_disconnect_cb (void *cls,
1024                     const struct GNUNET_PeerIdentity *peer,
1025                     void *peer_cls)
1026 {
1027   struct CadetPeer *cp = peer_cls;
1028
1029   LOG (GNUNET_ERROR_TYPE_DEBUG,
1030        "CORE connection to peer %s went down.\n",
1031        GNUNET_i2s (peer));
1032   GCP_set_mq (cp,
1033               NULL);
1034 }
1035
1036
1037 /**
1038  * Initialize the CORE subsystem.
1039  *
1040  * @param c Configuration.
1041  */
1042 void
1043 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1044 {
1045   struct GNUNET_MQ_MessageHandler handlers[] = {
1046     GNUNET_MQ_hd_var_size (connection_create,
1047                            GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1048                            struct GNUNET_CADET_ConnectionCreateMessage,
1049                            NULL),
1050     GNUNET_MQ_hd_fixed_size (connection_create_ack,
1051                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1052                              struct GNUNET_CADET_ConnectionCreateAckMessage,
1053                              NULL),
1054     GNUNET_MQ_hd_fixed_size (connection_broken,
1055                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1056                              struct GNUNET_CADET_ConnectionBrokenMessage,
1057                              NULL),
1058     GNUNET_MQ_hd_fixed_size (connection_destroy,
1059                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1060                              struct GNUNET_CADET_ConnectionDestroyMessage,
1061                              NULL),
1062     GNUNET_MQ_hd_fixed_size (tunnel_kx,
1063                              GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1064                              struct GNUNET_CADET_TunnelKeyExchangeMessage,
1065                              NULL),
1066     GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1067                              GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1068                              struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1069                              NULL),
1070     GNUNET_MQ_hd_var_size (tunnel_encrypted,
1071                            GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1072                            struct GNUNET_CADET_TunnelEncryptedMessage,
1073                            NULL),
1074     GNUNET_MQ_handler_end ()
1075   };
1076
1077   if (GNUNET_OK !=
1078       GNUNET_CONFIGURATION_get_value_number (c,
1079                                              "CADET",
1080                                              "MAX_ROUTES",
1081                                              &max_routes))
1082     max_routes = 10000;
1083   routes = GNUNET_CONTAINER_multishortmap_create (1024,
1084                                                   GNUNET_NO);
1085   route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1086   core = GNUNET_CORE_connect (c,
1087                               NULL,
1088                               &core_init_cb,
1089                               &core_connect_cb,
1090                               &core_disconnect_cb,
1091                               handlers);
1092 }
1093
1094
1095 /**
1096  * Shut down the CORE subsystem.
1097  */
1098 void
1099 GCO_shutdown ()
1100 {
1101   if (NULL != core)
1102   {
1103     GNUNET_CORE_disconnect (core);
1104     core = NULL;
1105   }
1106   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1107   GNUNET_CONTAINER_multishortmap_destroy (routes);
1108   routes = NULL;
1109   GNUNET_CONTAINER_heap_destroy (route_heap);
1110   route_heap = NULL;
1111   if (NULL != timeout_task)
1112   {
1113     GNUNET_SCHEDULER_cancel (timeout_task);
1114     timeout_task = NULL;
1115   }
1116 }
1117
1118 /* end of gnunet-cadet-service_core.c */