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