work towards 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    * Message queue notifications for @e prev_hop.
61    */
62   struct GCP_MessageQueueManager *prev_mqm;
63
64   /**
65    * Message queue notifications for @e next_hop.
66    */
67   struct GCP_MessageQueueManager *next_mqm;
68
69   /**
70    * Unique identifier for the connection that uses this route.
71    */
72   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
73
74   /**
75    * When was this route last in use?
76    */
77   struct GNUNET_TIME_Absolute last_use;
78
79 };
80
81
82 /**
83  * Handle to the CORE service.
84  */
85 static struct GNUNET_CORE_Handle *core;
86
87 /**
88  * Routes on which this peer is an intermediate.
89  */
90 static struct GNUNET_CONTAINER_MultiShortmap *routes;
91
92
93 /**
94  * Get the route corresponding to a hash.
95  *
96  * @param cid hash generated from the connection identifier
97  */
98 static struct CadetRoute *
99 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
100 {
101   return GNUNET_CONTAINER_multishortmap_get (routes,
102                                              &cid->connection_of_tunnel);
103 }
104
105
106 /**
107  * We message @a msg from @a prev.  Find its route by @a cid and
108  * forward to the next hop.  Drop and signal broken route if we do not
109  * have a route.
110  *
111  * @param prev previous hop (sender)
112  * @param cid connection identifier, tells us which route to use
113  * @param msg the message to forward
114  */
115 static void
116 route_message (struct CadetPeer *prev,
117                const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
118                const struct GNUNET_MessageHeader *msg)
119 {
120   struct CadetRoute *route;
121
122   route = get_route (cid);
123   if (NULL == route)
124   {
125     struct GNUNET_MQ_Envelope *env;
126     struct GNUNET_CADET_ConnectionBrokenMessage *bm;
127
128     env = GNUNET_MQ_msg (bm,
129                          GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
130     bm->cid = *cid;
131     bm->peer1 = my_full_id;
132     GCP_send (prev,
133               env);
134     return;
135   }
136   /* FIXME: support round-robin queue management here somewhere! */
137   GCP_send ((prev == route->prev_hop) ? route->next_hop : route->prev_hop,
138             GNUNET_MQ_msg_copy (msg));
139 }
140
141
142 /**
143  * Check if the create_connection message has the appropriate size.
144  *
145  * @param cls Closure (unused).
146  * @param msg Message to check.
147  *
148  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
149  */
150 static int
151 check_connection_create (void *cls,
152                          const struct GNUNET_CADET_ConnectionCreateMessage *msg)
153 {
154   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
155
156   if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
157   {
158     GNUNET_break_op (0);
159     return GNUNET_NO;
160   }
161   return GNUNET_YES;
162 }
163
164
165 /**
166  * Destroy our state for @a route.
167  *
168  * @param route route to destroy
169  */
170 static void
171 destroy_route (struct CadetRoute *route)
172 {
173   GCP_request_mq_cancel (route->next_mqm);
174   GCP_request_mq_cancel (route->prev_mqm);
175   GNUNET_free (route);
176 }
177
178
179 /**
180  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
181  *
182  * @param cls Closure (CadetPeer for neighbor that sent the message).
183  * @param msg Message itself.
184  */
185 static void
186 handle_connection_create (void *cls,
187                           const struct GNUNET_CADET_ConnectionCreateMessage *msg)
188 {
189   struct CadetPeer *sender = cls;
190   struct CadetPeer *next;
191   const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
192   struct CadetRoute *route;
193   uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
194   unsigned int path_length;
195   unsigned int off;
196
197   path_length = size / sizeof (struct GNUNET_PeerIdentity);
198   /* Initiator is at offset 0. */
199   for (off=1;off<path_length;off++)
200     if (0 == memcmp (&my_full_id,
201                      &pids[off],
202                      sizeof (struct GNUNET_PeerIdentity)))
203       break;
204   if (off == path_length)
205   {
206     /* We are not on the path, bogus request */
207     GNUNET_break_op (0);
208     return;
209   }
210   /* Check previous hop */
211   if (sender != GCP_get (&pids[off - 1],
212                          GNUNET_NO))
213   {
214     /* sender is not on the path, not allowed */
215     GNUNET_break_op (0);
216     return;
217   }
218   if (off == path_length - 1)
219   {
220     /* We are the destination, create connection */
221     return;
222   }
223   /* We are merely a hop on the way, check if we can support the route */
224   next = GCP_get (&pids[off + 1],
225                   GNUNET_NO);
226   if (NULL == next)
227   {
228     /* unworkable, send back BROKEN */
229     GNUNET_break (0); // FIXME...
230     return;
231   }
232
233   route = GNUNET_new (struct CadetRoute);
234
235 #if FIXME
236   GCC_handle_create (peer,
237                      &msg->cid,
238                      path_length,
239                      route);
240 #endif
241 }
242
243
244 /**
245  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
246  *
247  * @param cls Closure (CadetPeer for neighbor that sent the message).
248  * @param msg Message itself.
249  */
250 static void
251 handle_connection_ack (void *cls,
252                        const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
253 {
254   struct CadetPeer *peer = cls;
255   struct CadetConnection *cc;
256
257   /* First, check if ACK belongs to a connection that ends here. */
258   cc = GNUNET_CONTAINER_multishortmap_get (connections,
259                                            &msg->cid.connection_of_tunnel);
260   if (NULL != cc)
261   {
262     /* verify ACK came from the right direction */
263     struct CadetPeerPath *path = GCC_get_path (cc);
264
265     if (peer !=
266         GCPP_get_peer_at_offset (path,
267                                  0))
268     {
269       /* received ACK from unexpected direction, ignore! */
270       GNUNET_break_op (0);
271       return;
272     }
273     GCC_handle_connection_ack (cc);
274     return;
275   }
276
277   /* We're just an intermediary peer, route the message along its path */
278   route_message (peer,
279                  &msg->cid,
280                  &msg->header);
281 }
282
283
284 /**
285  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
286  *
287  * @param cls Closure (CadetPeer for neighbor that sent the message).
288  * @param msg Message itself.
289  * @deprecated duplicate logic with #handle_destroy(); dedup!
290  */
291 static void
292 handle_connection_broken (void *cls,
293                           const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
294 {
295   struct CadetPeer *peer = cls;
296   struct CadetConnection *cc;
297   struct CadetRoute *route;
298
299   /* First, check if message belongs to a connection that ends here. */
300   cc = GNUNET_CONTAINER_multishortmap_get (connections,
301                                            &msg->cid.connection_of_tunnel);
302   if (NULL != cc)
303   {
304     /* verify message came from the right direction */
305     struct CadetPeerPath *path = GCC_get_path (cc);
306
307     if (peer !=
308         GCPP_get_peer_at_offset (path,
309                                  0))
310     {
311       /* received message from unexpected direction, ignore! */
312       GNUNET_break_op (0);
313       return;
314     }
315     GCC_destroy (cc);
316
317     /* FIXME: also destroy the path up to the specified link! */
318     return;
319   }
320
321   /* We're just an intermediary peer, route the message along its path */
322   route = get_route (&msg->cid);
323   route_message (peer,
324                  &msg->cid,
325                  &msg->header);
326   destroy_route (route);
327   /* FIXME: also destroy paths we MAY have up to the specified link! */
328 }
329
330
331 /**
332  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
333  *
334  * @param cls Closure (CadetPeer for neighbor that sent the message).
335  * @param msg Message itself.
336  */
337 static void
338 handle_connection_destroy (void *cls,
339                            const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
340 {
341   struct CadetPeer *peer = cls;
342   struct CadetConnection *cc;
343   struct CadetRoute *route;
344
345   /* First, check if message belongs to a connection that ends here. */
346   cc = GNUNET_CONTAINER_multishortmap_get (connections,
347                                            &msg->cid.connection_of_tunnel);
348   if (NULL != cc)
349   {
350     /* verify message came from the right direction */
351     struct CadetPeerPath *path = GCC_get_path (cc);
352
353     if (peer !=
354         GCPP_get_peer_at_offset (path,
355                                  0))
356     {
357       /* received message from unexpected direction, ignore! */
358       GNUNET_break_op (0);
359       return;
360     }
361     GCC_destroy (cc);
362     return;
363   }
364
365   /* We're just an intermediary peer, route the message along its path */
366   route = get_route (&msg->cid);
367   route_message (peer,
368                  &msg->cid,
369                  &msg->header);
370   destroy_route (route);
371 }
372
373
374 /**
375  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_HOP_BY_HOP_ENCRYPTED_ACK.
376  *
377  * @param cls Closure (CadetPeer for neighbor that sent the message).
378  * @param msg Message itself.
379  */
380 static void
381 handle_hop_by_hop_encrypted_ack (void *cls,
382                                  const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
383 {
384   struct CadetPeer *peer = cls;
385
386 #if FIXME
387   GCC_handle_poll (peer,
388                    msg);
389 #endif
390 }
391
392
393 /**
394  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
395  *
396  * @param cls Closure (CadetPeer for neighbor that sent the message).
397  * @param msg Message itself.
398  */
399 static void
400 handle_poll (void *cls,
401              const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
402 {
403   struct CadetPeer *peer = cls;
404
405 #if FIXME
406   GCC_handle_poll (peer,
407                    msg);
408 #endif
409 }
410
411
412 /**
413  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
414  *
415  * @param cls Closure (CadetPeer for neighbor that sent the message).
416  * @param msg Message itself.
417  */
418 static void
419 handle_tunnel_kx (void *cls,
420                   const struct GNUNET_CADET_TunnelKeyExchangeMessage *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_kx (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  * Check if the encrypted message has the appropriate size.
455  *
456  * @param cls Closure (unused).
457  * @param msg Message to check.
458  *
459  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
460  */
461 static int
462 check_tunnel_encrypted (void *cls,
463                         const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
464 {
465   return GNUNET_YES;
466 }
467
468
469 /**
470  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
471  *
472  * @param cls Closure (CadetPeer for neighbor that sent the message).
473  * @param msg Message itself.
474  */
475 static void
476 handle_tunnel_encrypted (void *cls,
477                          const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
478 {
479   struct CadetPeer *peer = cls;
480   struct CadetConnection *cc;
481
482   /* First, check if message belongs to a connection that ends here. */
483   cc = GNUNET_CONTAINER_multishortmap_get (connections,
484                                            &msg->cid.connection_of_tunnel);
485   if (NULL != cc)
486   {
487     /* verify message came from the right direction */
488     struct CadetPeerPath *path = GCC_get_path (cc);
489
490     if (peer !=
491         GCPP_get_peer_at_offset (path,
492                                  0))
493     {
494       /* received message from unexpected direction, ignore! */
495       GNUNET_break_op (0);
496       return;
497     }
498     GCC_handle_encrypted (cc,
499                           msg);
500     return;
501   }
502
503   /* We're just an intermediary peer, route the message along its path */
504   route_message (peer,
505                  &msg->cid,
506                  &msg->header);
507 }
508
509
510 /**
511  * Function called after #GNUNET_CORE_connect has succeeded (or failed
512  * for good).  Note that the private key of the peer is intentionally
513  * not exposed here; if you need it, your process should try to read
514  * the private key file directly (which should work if you are
515  * authorized...).  Implementations of this function must not call
516  * #GNUNET_CORE_disconnect (other than by scheduling a new task to
517  * do this later).
518  *
519  * @param cls closure
520  * @param my_identity ID of this peer, NULL if we failed
521  */
522 static void
523 core_init_cb (void *cls,
524               const struct GNUNET_PeerIdentity *my_identity)
525 {
526   if (NULL == my_identity)
527   {
528     GNUNET_break (0);
529     return;
530   }
531   GNUNET_break (0 ==
532                 memcmp (my_identity,
533                         &my_full_id,
534                         sizeof (struct GNUNET_PeerIdentity)));
535 }
536
537
538 /**
539  * Method called whenever a given peer connects.
540  *
541  * @param cls closure
542  * @param peer peer identity this notification is about
543  */
544 static void *
545 core_connect_cb (void *cls,
546                  const struct GNUNET_PeerIdentity *peer,
547                  struct GNUNET_MQ_Handle *mq)
548 {
549   struct CadetPeer *cp;
550
551   cp = GCP_get (peer,
552                 GNUNET_YES);
553   GCP_set_mq (cp,
554               mq);
555   return cp;
556 }
557
558
559 /**
560  * Method called whenever a peer disconnects.
561  *
562  * @param cls closure
563  * @param peer peer identity this notification is about
564  */
565 static void
566 core_disconnect_cb (void *cls,
567                     const struct GNUNET_PeerIdentity *peer,
568                     void *peer_cls)
569 {
570   struct CadetPeer *cp = peer_cls;
571
572   /* FIXME: also check all routes going via peer and
573      send broken messages to the other direction! */
574   GNUNET_break (0);
575   GCP_set_mq (cp,
576               NULL);
577 }
578
579
580 /**
581  * Initialize the CORE subsystem.
582  *
583  * @param c Configuration.
584  */
585 void
586 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
587 {
588   struct GNUNET_MQ_MessageHandler handlers[] = {
589     GNUNET_MQ_hd_var_size (connection_create,
590                            GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
591                            struct GNUNET_CADET_ConnectionCreateMessage,
592                            NULL),
593     GNUNET_MQ_hd_fixed_size (connection_ack,
594                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
595                              struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
596                              NULL),
597     GNUNET_MQ_hd_fixed_size (connection_broken,
598                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
599                              struct GNUNET_CADET_ConnectionBrokenMessage,
600                              NULL),
601     GNUNET_MQ_hd_fixed_size (connection_destroy,
602                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
603                              struct GNUNET_CADET_ConnectionDestroyMessage,
604                              NULL),
605     GNUNET_MQ_hd_fixed_size (hop_by_hop_encrypted_ack,
606                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
607                              struct GNUNET_CADET_ConnectionEncryptedAckMessage,
608                              NULL),
609     GNUNET_MQ_hd_fixed_size (poll,
610                              GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
611                              struct GNUNET_CADET_ConnectionHopByHopPollMessage,
612                              NULL),
613     GNUNET_MQ_hd_fixed_size (tunnel_kx,
614                              GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
615                              struct GNUNET_CADET_TunnelKeyExchangeMessage,
616                              NULL),
617     GNUNET_MQ_hd_var_size (tunnel_encrypted,
618                            GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
619                            struct GNUNET_CADET_TunnelEncryptedMessage,
620                            NULL),
621     GNUNET_MQ_handler_end ()
622   };
623
624   routes = GNUNET_CONTAINER_multishortmap_create (1024,
625                                                   GNUNET_NO);
626   core = GNUNET_CORE_connect (c,
627                               NULL,
628                               &core_init_cb,
629                               &core_connect_cb,
630                               &core_disconnect_cb,
631                               handlers);
632 }
633
634
635 /**
636  * Shut down the CORE subsystem.
637  */
638 void
639 GCO_shutdown ()
640 {
641   if (NULL != core)
642   {
643     GNUNET_CORE_disconnect (core);
644     core = NULL;
645   }
646   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
647   GNUNET_CONTAINER_multishortmap_destroy (routes);
648 }
649
650 /* end of gnunet-cadet-service_core.c */