starting re-implementation of CADET service
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_peer.c
1
2 /*
3      This file is part of GNUnet.
4      Copyright (C) 2001-2017 GNUnet e.V.
5
6      GNUnet is free software; you can redistribute it and/or modify
7      it under the terms of the GNU General Public License as published
8      by the Free Software Foundation; either version 3, or (at your
9      option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      General Public License for more details.
15
16      You should have received a copy of the GNU General Public License
17      along with GNUnet; see the file COPYING.  If not, write to the
18      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19      Boston, MA 02110-1301, USA.
20 */
21
22 /**
23  * @file cadet/gnunet-service-cadet-new_peer.c
24  * @brief Information we track per peer.
25  * @author Bartlomiej Polot
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_signatures.h"
31 #include "gnunet_transport_service.h"
32 #include "gnunet_ats_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "cadet_protocol.h"
36 #include "cadet_path.h"
37 #include "gnunet-service-cadet-new.h"
38 #include "gnunet-service-cadet-new_dht.h"
39 #include "gnunet-service-cadet-new_peer.h"
40 #include "gnunet-service-cadet-new_tunnels.h"
41
42 /**
43  * How long do we wait until tearing down an idle peer?
44  */
45 #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
46
47
48 /**
49  * Struct containing all information regarding a given peer
50  */
51 struct CadetPeer
52 {
53   /**
54    * ID of the peer
55    */
56   struct GNUNET_PeerIdentity pid;
57
58   /**
59    * Last time we heard from this peer
60    */
61   struct GNUNET_TIME_Absolute last_contact;
62
63   /**
64    * Paths to reach the peer, ordered by ascending hop count
65    */
66   struct CadetPeerPath *path_head;
67
68   /**
69    * Paths to reach the peer, ordered by ascending hop count
70    */
71   struct CadetPeerPath *path_tail;
72
73   /**
74    * Handle to stop the DHT search for paths to this peer
75    */
76   struct GCD_search_handle *search_h;
77
78   /**
79    * Task to stop the DHT search for paths to this peer
80    */
81   struct GNUNET_SCHEDULER_Task *search_delayed;
82
83   /**
84    * Task to destroy this entry.
85    */
86   struct GNUNET_SCHEDULER_Task *destroy_task;
87
88   /**
89    * Tunnel to this peer, if any.
90    */
91   struct CadetTunnel *t;
92
93   /**
94    * Connections that go through this peer; indexed by tid.
95    */
96   struct GNUNET_CONTAINER_MultiHashMap *connections;
97
98   /**
99    * Handle for core transmissions.
100    */
101   struct GNUNET_MQ_Handle *core_mq;
102
103   /**
104    * Hello message of the peer.
105    */
106   struct GNUNET_HELLO_Message *hello;
107
108   /**
109    * Handle to us offering the HELLO to the transport.
110    */
111   struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
112
113   /**
114    * Handle to our ATS request asking ATS to suggest an address
115    * to TRANSPORT for this peer (to establish a direct link).
116    */
117   struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
118
119   /**
120    * How many messages are in the queue to this peer.
121    */
122   unsigned int queue_n;
123
124   /**
125    * How many paths do we have to this peer (in the @e path_head DLL).
126    */
127   unsigned int num_paths;
128
129 };
130
131
132 /**
133  * Get the static string for a peer ID.
134  *
135  * @param peer Peer.
136  *
137  * @return Static string for it's ID.
138  */
139 const char *
140 GCP_2s (const struct CadetPeer *peer)
141 {
142   if (NULL == peer)
143     return "PEER(NULL)";
144   return GNUNET_i2s (&peer->pid);
145 }
146
147
148 /**
149  * This peer is no longer be needed, clean it up now.
150  *
151  * @param cls peer to clean up
152  */
153 static void
154 destroy_peer (void *cls)
155 {
156   struct CadetPeer *cp = cls;
157
158   cp->destroy_task = NULL;
159   GNUNET_assert (NULL == cp->t);
160   GNUNET_assert (NULL == cp->core_mq);
161   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (cp->connections));
162   GNUNET_assert (GNUNET_YES ==
163                  GNUNET_CONTAINER_multipeermap_remove (peers,
164                                                        &cp->pid,
165                                                        cp));
166   /* FIXME: clean up paths! */
167   /* FIXME: clean up search_h! */
168   /* FIXME: clean up search_delayed! */
169
170   GNUNET_CONTAINER_multihashmap_destroy (cp->connections);
171   GNUNET_free_non_null (cp->hello);
172   if (NULL != cp->hello_offer)
173   {
174     GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
175     cp->hello_offer = NULL;
176   }
177   if (NULL != cp->connectivity_suggestion)
178   {
179     GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
180     cp->connectivity_suggestion = NULL;
181   }
182   GNUNET_free (cp);
183 }
184
185
186 /**
187  * Function called to destroy a peer now.
188  *
189  * @param cls NULL
190  * @param pid identity of the peer (unused)
191  * @param value the `struct CadetPeer` to clean up
192  * @return #GNUNET_OK (continue to iterate)
193  */
194 static int
195 destroy_iterator_cb (void *cls,
196                      const struct GNUNET_PeerIdentity *pid,
197                      void *value)
198 {
199   struct CadetPeer *cp = value;
200
201   if (NULL != cp->destroy_task)
202     GNUNET_SCHEDULER_cancel (cp->destroy_task);
203   destroy_peer (cp);
204   return GNUNET_OK;
205 }
206
207
208 /**
209  * Clean up all entries about all peers.
210  * Must only be called after all tunnels, CORE-connections and
211  * connections are down.
212  */
213 void
214 GCP_destroy_all_peers ()
215 {
216   GNUNET_CONTAINER_multipeermap_iterate (peers,
217                                          &destroy_iterator_cb,
218                                          NULL);
219 }
220
221
222 /**
223  * This peer may no longer be needed, consider cleaning it up.
224  *
225  * @param peer peer to clean up
226  */
227 static void
228 consider_peer_destroy (struct CadetPeer *peer)
229 {
230   struct GNUNET_TIME_Relative exp;
231
232   if (NULL != peer->destroy_task)
233   {
234     GNUNET_SCHEDULER_cancel (peer->destroy_task);
235     peer->destroy_task = NULL;
236   }
237   if (NULL != peer->t)
238     return; /* still relevant! */
239   if (NULL != peer->core_mq)
240     return; /* still relevant! */
241   if (0 != GNUNET_CONTAINER_multihashmap_size (peer->connections))
242     return; /* still relevant! */
243   if (NULL != peer->hello)
244   {
245     /* relevant only until HELLO expires */
246     exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (peer->hello));
247     peer->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
248                                                        &destroy_peer,
249                                                        peer);
250     return;
251   }
252   peer->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
253                                                      &destroy_peer,
254                                                      peer);
255 }
256
257
258 /**
259  * Function called when the DHT finds a @a path to the peer (@a cls).
260  *
261  * @param cls the `struct CadetPeer`
262  * @param path the path that was found
263  */
264 static void
265 dht_result_cb (void *cls,
266                const struct CadetPeerPath *path)
267 {
268   struct CadetPeer *peer = cls;
269
270   // FIXME: handle path!
271 }
272
273
274 /**
275  * This peer is now on more "active" duty, activate processes related to it.
276  *
277  * @param peer the more-active peer
278  */
279 static void
280 consider_peer_activate (struct CadetPeer *peer)
281 {
282   uint32_t strength;
283
284   if (NULL != peer->destroy_task)
285   {
286     /* It's active, do not destory! */
287     GNUNET_SCHEDULER_cancel (peer->destroy_task);
288     peer->destroy_task = NULL;
289   }
290   if (NULL == peer->core_mq)
291   {
292     /* Lacks direct connection, try to create one by querying the DHT */
293     if ( (NULL == peer->search_h) &&
294          (DESIRED_CONNECTIONS_PER_TUNNEL < peer->num_paths) )
295       peer->search_h
296         = GCD_search (&peer->pid,
297                       &dht_result_cb,
298                       peer);
299   }
300   else
301   {
302     /* Have direct connection, stop DHT search if active */
303     if (NULL != peer->search_h)
304     {
305       GCD_search_stop (peer->search_h);
306       peer->search_h = NULL;
307     }
308   }
309
310   /* If we have a tunnel, our urge for connections is much bigger */
311   strength = (NULL != peer->t) ? 32 : 1;
312   if (NULL != peer->connectivity_suggestion)
313     GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion);
314   peer->connectivity_suggestion
315     = GNUNET_ATS_connectivity_suggest (ats_ch,
316                                        &peer->pid,
317                                        strength);
318 }
319
320
321 /**
322  * Retrieve the CadetPeer stucture associated with the
323  * peer. Optionally create one and insert it in the appropriate
324  * structures if the peer is not known yet.
325  *
326  * @param peer_id Full identity of the peer.
327  * @param create #GNUNET_YES if a new peer should be created if unknown.
328  *               #GNUNET_NO to return NULL if peer is unknown.
329  * @return Existing or newly created peer structure.
330  *         NULL if unknown and not requested @a create
331  */
332 struct CadetPeer *
333 GCP_get (const struct GNUNET_PeerIdentity *peer_id,
334          int create)
335 {
336   struct CadetPeer *cp;
337
338   cp = GNUNET_CONTAINER_multipeermap_get (peers,
339                                           peer_id);
340   if (NULL != cp)
341     return cp;
342   if (GNUNET_NO == create)
343     return NULL;
344   cp = GNUNET_new (struct CadetPeer);
345   cp->pid = *peer_id;
346   cp->connections = GNUNET_CONTAINER_multihashmap_create (32,
347                                                           GNUNET_YES);
348   cp->search_h = NULL; // FIXME: start search immediately!?
349   cp->connectivity_suggestion = NULL; // FIXME: request with ATS!?
350
351   GNUNET_assert (GNUNET_YES ==
352                  GNUNET_CONTAINER_multipeermap_put (peers,
353                                                     &cp->pid,
354                                                     cp,
355                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
356   return cp;
357 }
358
359
360 /**
361  * Obtain the peer identity for a `struct CadetPeer`.
362  *
363  * @param cp our peer handle
364  * @param[out] peer_id where to write the peer identity
365  */
366 void
367 GCP_id (struct CadetPeer *cp,
368         struct GNUNET_PeerIdentity *peer_id)
369 {
370   *peer_id = cp->pid;
371 }
372
373
374 /**
375  * Create a peer path based on the result of a DHT lookup.
376  *
377  * @param get_path path of the get request
378  * @param get_path_length lenght of @a get_path
379  * @param put_path path of the put request
380  * @param put_path_length length of the @a put_path
381  * @return a path through the network
382  */
383 struct CadetPeerPath *
384 GCP_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
385                    unsigned int get_path_length,
386                    const struct GNUNET_PeerIdentity *put_path,
387                    unsigned int put_path_length)
388 {
389   GNUNET_assert (0); // FIXME: implement!
390   return NULL;
391 }
392
393
394 /**
395  * Iterate over all known peers.
396  *
397  * @param iter Iterator.
398  * @param cls Closure for @c iter.
399  */
400 void
401 GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
402                  void *cls)
403 {
404   GNUNET_CONTAINER_multipeermap_iterate (peers,
405                                          iter,
406                                          cls);
407 }
408
409
410 /**
411  * Count the number of known paths toward the peer.
412  *
413  * @param peer Peer to get path info.
414  * @return Number of known paths.
415  */
416 unsigned int
417 GCP_count_paths (const struct CadetPeer *peer)
418 {
419   return peer->num_paths;
420 }
421
422
423 /**
424  * Iterate over the paths to a peer.
425  *
426  * @param peer Peer to get path info.
427  * @param callback Function to call for every path.
428  * @param callback_cls Closure for @a callback.
429  * @return Number of iterated paths.
430  */
431 unsigned int
432 GCP_iterate_paths (struct CadetPeer *peer,
433                    GCP_PathIterator callback,
434                    void *callback_cls)
435 {
436   unsigned int ret = 0;
437
438   for (struct CadetPeerPath *path = peer->path_head;
439        NULL != path;
440        path = path->next)
441   {
442     if (GNUNET_NO ==
443         callback (callback_cls,
444                   peer,
445                   path))
446       return ret;
447     ret++;
448   }
449   return ret;
450 }
451
452
453 /**
454  * Get the tunnel towards a peer.
455  *
456  * @param peer Peer to get from.
457  * @param create #GNUNET_YES to create a tunnel if we do not have one
458  * @return Tunnel towards peer.
459  */
460 struct CadetTunnel *
461 GCP_get_tunnel (struct CadetPeer *peer,
462                 int create)
463 {
464   if (NULL == peer)
465     return NULL;
466   if ( (NULL != peer->t) ||
467        (GNUNET_NO == create) )
468     return peer->t;
469   peer->t = GCT_create_tunnel (peer);
470   consider_peer_activate (peer);
471   return peer->t;
472 }
473
474
475 /**
476  * We got a HELLO for a @a peer, remember it, and possibly
477  * trigger adequate actions (like trying to connect).
478  *
479  * @param peer the peer we got a HELLO for
480  * @param hello the HELLO to remember
481  */
482 void
483 GCP_set_hello (struct CadetPeer *peer,
484                const struct GNUNET_HELLO_Message *hello)
485 {
486   /* FIXME! */
487
488   consider_peer_destroy (peer);
489 }
490
491
492 /**
493  * The tunnel to the given peer no longer exists, remove it from our
494  * data structures, and possibly clean up the peer itself.
495  *
496  * @param peer the peer affected
497  * @param t the dead tunnel
498  */
499 void
500 GCP_drop_tunnel (struct CadetPeer *peer,
501                  struct CadetTunnel *t)
502 {
503   GNUNET_assert (peer->t == t);
504   peer->t = NULL;
505   consider_peer_destroy (peer);
506 }
507
508
509 /* end of gnunet-service-cadet-new_peer.c */