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