cadet message struct and type rename-fest
[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_ConnectionBrokenMessage *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_ConnectionCreateMessage *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_ConnectionCreateMessage *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_CREATE_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_ConnectionCreateMessageAckMessage *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_ConnectionBrokenMessage *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
263     /* FIXME: also destroy the path up to the specified link! */
264     return;
265   }
266
267   /* We're just an intermediary peer, route the message along its path */
268   route = get_route (&msg->cid);
269   route_message (peer,
270                  &msg->cid,
271                  &msg->header);
272   destroy_route (route);
273   /* FIXME: also destroy paths we MAY have up to the specified link! */
274 }
275
276
277 /**
278  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
279  *
280  * @param cls Closure (CadetPeer for neighbor that sent the message).
281  * @param msg Message itself.
282  */
283 static void
284 handle_destroy (void *cls,
285                 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
286 {
287   struct CadetPeer *peer = cls;
288   struct CadetConnection *cc;
289   struct CadetRoute *route;
290
291   /* First, check if message belongs to a connection that ends here. */
292   cc = GNUNET_CONTAINER_multishortmap_get (connections,
293                                            &msg->cid.connection_of_tunnel);
294   if (NULL != cc)
295   {
296     /* verify message came from the right direction */
297     struct CadetPeerPath *path = GCC_get_path (cc);
298
299     if (peer !=
300         GCPP_get_peer_at_offset (path,
301                                  0))
302     {
303       /* received message from unexpected direction, ignore! */
304       GNUNET_break_op (0);
305       return;
306     }
307     GCC_destroy (cc);
308     return;
309   }
310
311   /* We're just an intermediary peer, route the message along its path */
312   route = get_route (&msg->cid);
313   route_message (peer,
314                  &msg->cid,
315                  &msg->header);
316   destroy_route (route);
317 }
318
319
320 /**
321  * Handle for #GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED_HOP_BY_HOP_ACK
322  *
323  * @param cls Closure (CadetPeer for neighbor that sent the message).
324  * @param msg Message itself.
325  */
326 static void
327 handle_ack (void *cls,
328             const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
329 {
330   struct CadetPeer *peer = cls;
331
332 #if FIXME
333   GCC_handle_ack (peer,
334                   msg);
335 #endif
336 }
337
338
339 /**
340  * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_POLL
341  *
342  * @param cls Closure (CadetPeer for neighbor that sent the message).
343  * @param msg Message itself.
344  */
345 static void
346 handle_poll (void *cls,
347              const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
348 {
349   struct CadetPeer *peer = cls;
350
351 #if FIXME
352   GCC_handle_poll (peer,
353                    msg);
354 #endif
355 }
356
357
358 /**
359  * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
360  *
361  * @param cls Closure (CadetPeer for neighbor that sent the message).
362  * @param msg Message itself.
363  */
364 static void
365 handle_kx (void *cls,
366            const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
367 {
368   struct CadetPeer *peer = cls;
369   struct CadetConnection *cc;
370
371   /* First, check if message belongs to a connection that ends here. */
372   cc = GNUNET_CONTAINER_multishortmap_get (connections,
373                                            &msg->cid.connection_of_tunnel);
374   if (NULL != cc)
375   {
376     /* verify message came from the right direction */
377     struct CadetPeerPath *path = GCC_get_path (cc);
378
379     if (peer !=
380         GCPP_get_peer_at_offset (path,
381                                  0))
382     {
383       /* received message from unexpected direction, ignore! */
384       GNUNET_break_op (0);
385       return;
386     }
387     GCC_handle_kx (cc,
388                    msg);
389     return;
390   }
391
392   /* We're just an intermediary peer, route the message along its path */
393   route_message (peer,
394                  &msg->cid,
395                  &msg->header);
396 }
397
398
399 /**
400  * Check if the encrypted message has the appropriate size.
401  *
402  * @param cls Closure (unused).
403  * @param msg Message to check.
404  *
405  * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
406  */
407 static int
408 check_encrypted (void *cls,
409                  const struct GNUNET_CADET_ConnectionEncryptedMessage *msg)
410 {
411   return GNUNET_YES;
412 }
413
414
415 /**
416  * Handle for #GNUNET_MESSAGE_TYPE_CONNECTION_ENCRYPTED.
417  *
418  * @param cls Closure (CadetPeer for neighbor that sent the message).
419  * @param msg Message itself.
420  */
421 static void
422 handle_encrypted (void *cls,
423                   const struct GNUNET_CADET_ConnectionEncryptedMessage *msg)
424 {
425   struct CadetPeer *peer = cls;
426   struct CadetConnection *cc;
427
428   /* First, check if message belongs to a connection that ends here. */
429   cc = GNUNET_CONTAINER_multishortmap_get (connections,
430                                            &msg->cid.connection_of_tunnel);
431   if (NULL != cc)
432   {
433     /* verify message came from the right direction */
434     struct CadetPeerPath *path = GCC_get_path (cc);
435
436     if (peer !=
437         GCPP_get_peer_at_offset (path,
438                                  0))
439     {
440       /* received message from unexpected direction, ignore! */
441       GNUNET_break_op (0);
442       return;
443     }
444     GCC_handle_encrypted (cc,
445                           msg);
446     return;
447   }
448
449   /* We're just an intermediary peer, route the message along its path */
450   route_message (peer,
451                  &msg->cid,
452                  &msg->header);
453 }
454
455
456 /**
457  * Function called after #GNUNET_CORE_connect has succeeded (or failed
458  * for good).  Note that the private key of the peer is intentionally
459  * not exposed here; if you need it, your process should try to read
460  * the private key file directly (which should work if you are
461  * authorized...).  Implementations of this function must not call
462  * #GNUNET_CORE_disconnect (other than by scheduling a new task to
463  * do this later).
464  *
465  * @param cls closure
466  * @param my_identity ID of this peer, NULL if we failed
467  */
468 static void
469 core_init_cb (void *cls,
470               const struct GNUNET_PeerIdentity *my_identity)
471 {
472   if (NULL == my_identity)
473   {
474     GNUNET_break (0);
475     return;
476   }
477   GNUNET_break (0 ==
478                 memcmp (my_identity,
479                         &my_full_id,
480                         sizeof (struct GNUNET_PeerIdentity)));
481 }
482
483
484 /**
485  * Method called whenever a given peer connects.
486  *
487  * @param cls closure
488  * @param peer peer identity this notification is about
489  */
490 static void *
491 core_connect_cb (void *cls,
492                  const struct GNUNET_PeerIdentity *peer,
493                  struct GNUNET_MQ_Handle *mq)
494 {
495   struct CadetPeer *cp;
496
497   cp = GCP_get (peer,
498                 GNUNET_YES);
499   GCP_set_mq (cp,
500               mq);
501   return cp;
502 }
503
504
505 /**
506  * Method called whenever a peer disconnects.
507  *
508  * @param cls closure
509  * @param peer peer identity this notification is about
510  */
511 static void
512 core_disconnect_cb (void *cls,
513                     const struct GNUNET_PeerIdentity *peer,
514                     void *peer_cls)
515 {
516   struct CadetPeer *cp = peer_cls;
517
518   /* FIXME: also check all routes going via peer and
519      send broken messages to the other direction! */
520   GNUNET_break (0);
521   GCP_set_mq (cp,
522               NULL);
523 }
524
525
526 /**
527  * Initialize the CORE subsystem.
528  *
529  * @param c Configuration.
530  */
531 void
532 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
533 {
534   struct GNUNET_MQ_MessageHandler handlers[] = {
535     GNUNET_MQ_hd_var_size (create,
536                            GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
537                            struct GNUNET_CADET_ConnectionCreateMessage,
538                            NULL),
539     GNUNET_MQ_hd_fixed_size (connection_ack,
540                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
541                              struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
542                              NULL),
543     GNUNET_MQ_hd_fixed_size (broken,
544                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
545                              struct GNUNET_CADET_ConnectionBrokenMessage,
546                              NULL),
547     GNUNET_MQ_hd_fixed_size (destroy,
548                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
549                              struct GNUNET_CADET_ConnectionDestroyMessage,
550                              NULL),
551     GNUNET_MQ_hd_fixed_size (ack,
552                              GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED_HOP_BY_HOP_ACK,
553                              struct GNUNET_CADET_ConnectionEncryptedAckMessage,
554                              NULL),
555     GNUNET_MQ_hd_fixed_size (poll,
556                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_POLL,
557                              struct GNUNET_CADET_ConnectionHopByHopPollMessage,
558                              NULL),
559     GNUNET_MQ_hd_fixed_size (kx,
560                              GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
561                              struct GNUNET_CADET_TunnelKeyExchangeMessage,
562                              NULL),
563     GNUNET_MQ_hd_var_size (encrypted,
564                            GNUNET_MESSAGE_TYPE_CONNECTION_ENCRYPTED,
565                            struct GNUNET_CADET_ConnectionEncryptedMessage,
566                            NULL),
567     GNUNET_MQ_handler_end ()
568   };
569
570   routes = GNUNET_CONTAINER_multishortmap_create (1024,
571                                                   GNUNET_NO);
572   core = GNUNET_CORE_connect (c,
573                               NULL,
574                               &core_init_cb,
575                               &core_connect_cb,
576                               &core_disconnect_cb,
577                               handlers);
578 }
579
580
581 /**
582  * Shut down the CORE subsystem.
583  */
584 void
585 GCO_shutdown ()
586 {
587   if (NULL != core)
588   {
589     GNUNET_CORE_disconnect (core);
590     core = NULL;
591   }
592   GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
593   GNUNET_CONTAINER_multishortmap_destroy (routes);
594 }
595
596 /* end of gnunet-cadet-service_core.c */