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