towards actual routing...
[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 #include "platform.h"
30 #include "gnunet-service-cadet-new_core.h"
31 #include "gnunet-service-cadet-new_paths.h"
32 #include "gnunet-service-cadet-new_peer.h"
33 #include "gnunet-service-cadet-new_connection.h"
34 #include "gnunet_core_service.h"
35 #include "cadet_protocol.h"
36
37
38 /**
39  * Description of a segment of a `struct CadetConnection` at the
40  * intermediate peers.  Routes are basically entries in a peer's
41  * routing table for forwarding traffic.  At both endpoints, the
42  * routes are terminated by a `struct CadetConnection`, which knows
43  * the complete `struct CadetPath` that is formed by the individual
44  * routes.
45  */
46 struct CadetRoute
47 {
48
49   /**
50    * Previous hop on this route.
51    */
52   struct CadetPeer *prev_hop;
53
54   /**
55    * Next hop on this route.
56    */
57   struct CadetPeer *next_hop;
58
59   /**
60    * Unique identifier for the connection that uses this route.
61    */
62   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
63
64   /**
65    * When was this route last in use?
66    */
67   struct GNUNET_TIME_Absolute last_use;
68
69 };
70
71
72 /**
73  * Handle to the CORE service.
74  */
75 static struct GNUNET_CORE_Handle *core;
76
77 /**
78  * Routes on which this peer is an intermediate.
79  */
80 static struct GNUNET_CONTAINER_MultiHashMap *routes;
81
82
83 /**
84  * Get the route corresponding to a hash.
85  *
86  * @param cid hash generated from the connection identifier
87  */
88 static struct CadetRoute *
89 get_route (const struct GNUNET_HashCode *cid)
90 {
91   return GNUNET_CONTAINER_multihashmap_get (routes,
92                                             cid);
93 }
94
95
96 /**
97  * We message @a msg from @a prev.  Find its route by @a cid and
98  * forward to the next hop.  Drop and signal broken route if we do not
99  * have a route.
100  *
101  * @param prev previous hop (sender)
102  * @param cid connection identifier, tells us which route to use
103  * @param msg the message to forward
104  */
105 static void
106 route_message (struct CadetPeer *prev,
107                const struct GNUNET_HashCode *cid, /* FIXME: bad type... */
108                const struct GNUNET_MessageHeader *msg)
109 {
110   struct CadetRoute *route;
111
112   route = get_route (cid);
113   if (NULL == route)
114   {
115     struct GNUNET_MQ_Envelope *env;
116     struct GNUNET_CADET_ConnectionBroken *bm;
117
118     env = GNUNET_MQ_msg (bm,
119                          GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
120     /* FIXME: ugly */
121     memcpy (&bm->cid,
122             cid,
123             sizeof (bm->cid));
124     bm->peer1 = my_full_id;
125     GCP_send (prev,
126               env);
127     return;
128   }
129   GNUNET_assert (0); /* FIXME: determine next hop from route and prev! */
130
131 }
132
133
134 /**
135  * Check if the create_connection message has the appropriate size.
136  *
137  * @param cls Closure (unused).
138  * @param msg Message to check.
139  *
140  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
141  */
142 static int
143 check_create (void *cls,
144               const struct GNUNET_CADET_ConnectionCreate *msg)
145 {
146   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
147
148   if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
149   {
150     GNUNET_break_op (0);
151     return GNUNET_NO;
152   }
153   return GNUNET_YES;
154 }
155
156
157 /**
158  * Destroy our state for @a route.
159  *
160  * @param route route to destroy
161  */
162 static void
163 destroy_route (struct CadetRoute *route)
164 {
165   GNUNET_break (0); // fIXME: implement!
166 }
167
168
169 /**
170  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
171  *
172  * @param cls Closure (CadetPeer for neighbor that sent the message).
173  * @param msg Message itself.
174  */
175 static void
176 handle_create (void *cls,
177                const struct GNUNET_CADET_ConnectionCreate *msg)
178 {
179   struct CadetPeer *peer = cls;
180   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
181   unsigned int path_length;
182
183   path_length = size / sizeof (struct GNUNET_PeerIdentity);
184 #if FIXME
185   GCC_handle_create (peer,
186                      &msg->cid,
187                      path_length,
188                      (const struct GNUNET_PeerIdentity *) &msg[1]);
189 #endif
190 }
191
192
193 /**
194  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK
195  *
196  * @param cls Closure (CadetPeer for neighbor that sent the message).
197  * @param msg Message itself.
198  */
199 static void
200 handle_connection_ack (void *cls,
201                        const struct GNUNET_CADET_ConnectionACK *msg)
202 {
203   struct CadetPeer *peer = cls;
204   const struct GNUNET_HashCode *cid = GCC_h2hc (&msg->cid.connection_of_tunnel);
205   struct CadetConnection *cc;
206
207   /* First, check if ACK belongs to a connection that ends here. */
208   cc = GNUNET_CONTAINER_multihashmap_get (connections,
209                                           cid);
210   if (NULL != cc)
211   {
212     /* verify ACK came from the right direction */
213     struct CadetPeerPath *path = GCC_get_path (cc);
214
215     if (peer !=
216         GCPP_get_peer_at_offset (path,
217                                  0))
218     {
219       /* received ACK from unexpected direction, ignore! */
220       GNUNET_break_op (0);
221       return;
222     }
223     GCC_handle_connection_ack (cc);
224     return;
225   }
226
227   /* We're just an intermediary peer, route the message along its path */
228   route_message (peer,
229                  cid,
230                  &msg->header);
231 }
232
233
234 /**
235  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
236  *
237  * @param cls Closure (CadetPeer for neighbor that sent the message).
238  * @param msg Message itself.
239  * @deprecated duplicate logic with #handle_destroy(); dedup!
240  */
241 static void
242 handle_broken (void *cls,
243                const struct GNUNET_CADET_ConnectionBroken *msg)
244 {
245   struct CadetPeer *peer = cls;
246   const struct GNUNET_HashCode *cid = GCC_h2hc (&msg->cid.connection_of_tunnel);
247   struct CadetConnection *cc;
248   struct CadetRoute *route;
249
250   /* First, check if message belongs to a connection that ends here. */
251   cc = GNUNET_CONTAINER_multihashmap_get (connections,
252                                           cid);
253   if (NULL != cc)
254   {
255     /* verify message came from the right direction */
256     struct CadetPeerPath *path = GCC_get_path (cc);
257
258     if (peer !=
259         GCPP_get_peer_at_offset (path,
260                                  0))
261     {
262       /* received message from unexpected direction, ignore! */
263       GNUNET_break_op (0);
264       return;
265     }
266     GCC_destroy (cc);
267     return;
268   }
269
270   /* We're just an intermediary peer, route the message along its path */
271   route = get_route (cid);
272   route_message (peer,
273                  cid,
274                  &msg->header);
275   destroy_route (route);
276 }
277
278
279 /**
280  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
281  *
282  * @param cls Closure (CadetPeer for neighbor that sent the message).
283  * @param msg Message itself.
284  */
285 static void
286 handle_destroy (void *cls,
287                 const struct GNUNET_CADET_ConnectionDestroy *msg)
288 {
289   struct CadetPeer *peer = cls;
290   const struct GNUNET_HashCode *cid = GCC_h2hc (&msg->cid.connection_of_tunnel);
291   struct CadetConnection *cc;
292   struct CadetRoute *route;
293
294   /* First, check if message belongs to a connection that ends here. */
295   cc = GNUNET_CONTAINER_multihashmap_get (connections,
296                                           cid);
297   if (NULL != cc)
298   {
299     /* verify message came from the right direction */
300     struct CadetPeerPath *path = GCC_get_path (cc);
301
302     if (peer !=
303         GCPP_get_peer_at_offset (path,
304                                  0))
305     {
306       /* received message from unexpected direction, ignore! */
307       GNUNET_break_op (0);
308       return;
309     }
310     GCC_destroy (cc);
311     return;
312   }
313
314   /* We're just an intermediary peer, route the message along its path */
315   route = get_route (cid);
316   route_message (peer,
317                  cid,
318                  &msg->header);
319   destroy_route (route);
320 }
321
322
323 /**
324  * Handle for #GNUNET_MESSAGE_TYPE_CADET_ACK
325  *
326  * @param cls Closure (CadetPeer for neighbor that sent the message).
327  * @param msg Message itself.
328  */
329 static void
330 handle_ack (void *cls,
331             const struct GNUNET_CADET_ACK *msg)
332 {
333   struct CadetPeer *peer = cls;
334
335 #if FIXME
336   GCC_handle_ack (peer,
337                   msg);
338 #endif
339 }
340
341
342 /**
343  * Handle for #GNUNET_MESSAGE_TYPE_CADET_POLL
344  *
345  * @param cls Closure (CadetPeer for neighbor that sent the message).
346  * @param msg Message itself.
347  */
348 static void
349 handle_poll (void *cls,
350              const struct GNUNET_CADET_Poll *msg)
351 {
352   struct CadetPeer *peer = cls;
353
354 #if FIXME
355   GCC_handle_poll (peer,
356                    msg);
357 #endif
358 }
359
360
361 /**
362  * Handle for #GNUNET_MESSAGE_TYPE_CADET_KX
363  *
364  * @param cls Closure (CadetPeer for neighbor that sent the message).
365  * @param msg Message itself.
366  */
367 static void
368 handle_kx (void *cls,
369            const struct GNUNET_CADET_KX *msg)
370 {
371   struct CadetPeer *peer = cls;
372   const struct GNUNET_HashCode *cid = GCC_h2hc (&msg->cid.connection_of_tunnel);
373   struct CadetConnection *cc;
374
375   /* First, check if message belongs to a connection that ends here. */
376   cc = GNUNET_CONTAINER_multihashmap_get (connections,
377                                           cid);
378   if (NULL != cc)
379   {
380     /* verify message came from the right direction */
381     struct CadetPeerPath *path = GCC_get_path (cc);
382
383     if (peer !=
384         GCPP_get_peer_at_offset (path,
385                                  0))
386     {
387       /* received message from unexpected direction, ignore! */
388       GNUNET_break_op (0);
389       return;
390     }
391     GCC_handle_kx (cc,
392                    msg);
393     return;
394   }
395
396   /* We're just an intermediary peer, route the message along its path */
397   route_message (peer,
398                  cid,
399                  &msg->header);
400 }
401
402
403 /**
404  * Check if the encrypted message has the appropriate size.
405  *
406  * @param cls Closure (unused).
407  * @param msg Message to check.
408  *
409  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
410  */
411 static int
412 check_encrypted (void *cls,
413                  const struct GNUNET_CADET_Encrypted *msg)
414 {
415   return GNUNET_YES;
416 }
417
418
419 /**
420  * Handle for #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED.
421  *
422  * @param cls Closure (CadetPeer for neighbor that sent the message).
423  * @param msg Message itself.
424  */
425 static void
426 handle_encrypted (void *cls,
427                   const struct GNUNET_CADET_Encrypted *msg)
428 {
429   struct CadetPeer *peer = cls;
430   const struct GNUNET_HashCode *cid = GCC_h2hc (&msg->cid.connection_of_tunnel);
431   struct CadetConnection *cc;
432
433   /* First, check if message belongs to a connection that ends here. */
434   cc = GNUNET_CONTAINER_multihashmap_get (connections,
435                                           cid);
436   if (NULL != cc)
437   {
438     /* verify message came from the right direction */
439     struct CadetPeerPath *path = GCC_get_path (cc);
440
441     if (peer !=
442         GCPP_get_peer_at_offset (path,
443                                  0))
444     {
445       /* received message from unexpected direction, ignore! */
446       GNUNET_break_op (0);
447       return;
448     }
449     GCC_handle_encrypted (cc,
450                           msg);
451     return;
452   }
453
454   /* We're just an intermediary peer, route the message along its path */
455   route_message (peer,
456                  cid,
457                  &msg->header);
458 }
459
460
461 /**
462  * Function called after #GNUNET_CORE_connect has succeeded (or failed
463  * for good).  Note that the private key of the peer is intentionally
464  * not exposed here; if you need it, your process should try to read
465  * the private key file directly (which should work if you are
466  * authorized...).  Implementations of this function must not call
467  * #GNUNET_CORE_disconnect (other than by scheduling a new task to
468  * do this later).
469  *
470  * @param cls closure
471  * @param my_identity ID of this peer, NULL if we failed
472  */
473 static void
474 core_init_cb (void *cls,
475               const struct GNUNET_PeerIdentity *my_identity)
476 {
477   if (NULL == my_identity)
478   {
479     GNUNET_break (0);
480     return;
481   }
482   GNUNET_break (0 ==
483                 memcmp (my_identity,
484                         &my_full_id,
485                         sizeof (struct GNUNET_PeerIdentity)));
486 }
487
488
489 /**
490  * Method called whenever a given peer connects.
491  *
492  * @param cls closure
493  * @param peer peer identity this notification is about
494  */
495 static void *
496 core_connect_cb (void *cls,
497                  const struct GNUNET_PeerIdentity *peer,
498                  struct GNUNET_MQ_Handle *mq)
499 {
500   struct CadetPeer *cp;
501
502   cp = GCP_get (peer,
503                 GNUNET_YES);
504   GCP_set_mq (cp,
505               mq);
506   return cp;
507 }
508
509
510 /**
511  * Method called whenever a peer disconnects.
512  *
513  * @param cls closure
514  * @param peer peer identity this notification is about
515  */
516 static void
517 core_disconnect_cb (void *cls,
518                     const struct GNUNET_PeerIdentity *peer,
519                     void *peer_cls)
520 {
521   struct CadetPeer *cp = peer_cls;
522
523   /* FIXME: also check all routes going via peer and
524      send broken messages to the other direction! */
525   GNUNET_break (0);
526   GCP_set_mq (cp,
527               NULL);
528 }
529
530
531 /**
532  * Initialize the CORE subsystem.
533  *
534  * @param c Configuration.
535  */
536 void
537 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
538 {
539   struct GNUNET_MQ_MessageHandler handlers[] = {
540     GNUNET_MQ_hd_var_size (create,
541                            GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
542                            struct GNUNET_CADET_ConnectionCreate,
543                            NULL),
544     GNUNET_MQ_hd_fixed_size (connection_ack,
545                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
546                              struct GNUNET_CADET_ConnectionACK,
547                              NULL),
548     GNUNET_MQ_hd_fixed_size (broken,
549                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
550                              struct GNUNET_CADET_ConnectionBroken,
551                              NULL),
552     GNUNET_MQ_hd_fixed_size (destroy,
553                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
554                              struct GNUNET_CADET_ConnectionDestroy,
555                              NULL),
556     GNUNET_MQ_hd_fixed_size (ack,
557                              GNUNET_MESSAGE_TYPE_CADET_ACK,
558                              struct GNUNET_CADET_ACK,
559                              NULL),
560     GNUNET_MQ_hd_fixed_size (poll,
561                              GNUNET_MESSAGE_TYPE_CADET_POLL,
562                              struct GNUNET_CADET_Poll,
563                              NULL),
564     GNUNET_MQ_hd_fixed_size (kx,
565                              GNUNET_MESSAGE_TYPE_CADET_KX,
566                              struct GNUNET_CADET_KX,
567                              NULL),
568     GNUNET_MQ_hd_var_size (encrypted,
569                            GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED,
570                            struct GNUNET_CADET_Encrypted,
571                            NULL),
572     GNUNET_MQ_handler_end ()
573   };
574
575   routes = GNUNET_CONTAINER_multihashmap_create (1024,
576                                                 GNUNET_NO);
577   core = GNUNET_CORE_connect (c,
578                               NULL,
579                               &core_init_cb,
580                               &core_connect_cb,
581                               &core_disconnect_cb,
582                               handlers);
583 }
584
585
586 /**
587  * Shut down the CORE subsystem.
588  */
589 void
590 GCO_shutdown ()
591 {
592   if (NULL != core)
593   {
594     GNUNET_CORE_disconnect (core);
595     core = NULL;
596   }
597   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (routes));
598   GNUNET_CONTAINER_multihashmap_destroy (routes);
599 }
600
601 /* end of gnunet-cadet-service_core.c */