more LOG macros
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_dht.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013, 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  * @file cadet/gnunet-service-cadet-new_dht.c
22  * @brief Information we track per peer.
23  * @author Bartlomiej Polot
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dht_service.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet-service-cadet-new.h"
32 #include "gnunet-service-cadet-new_dht.h"
33 #include "gnunet-service-cadet-new_hello.h"
34 #include "gnunet-service-cadet-new_peer.h"
35 #include "gnunet-service-cadet-new_paths.h"
36
37 #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
38
39
40 /**
41  * Handle for DHT searches.
42  */
43 struct GCD_search_handle
44 {
45   /**
46    * DHT_GET handle.
47    */
48   struct GNUNET_DHT_GetHandle *dhtget;
49
50 };
51
52
53 /**
54  * Handle to use DHT.
55  */
56 static struct GNUNET_DHT_Handle *dht_handle;
57
58 /**
59  * How often to PUT own ID in the DHT.
60  */
61 static struct GNUNET_TIME_Relative id_announce_time;
62
63 /**
64  * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
65  */
66 static unsigned long long dht_replication_level;
67
68 /**
69  * Task to periodically announce itself in the network.
70  */
71 static struct GNUNET_SCHEDULER_Task *announce_id_task;
72
73 /**
74  * Delay for the next ID announce.
75  */
76 static struct GNUNET_TIME_Relative announce_delay;
77
78
79 /**
80  * Function to process paths received for a new peer addition. The recorded
81  * paths form the initial tunnel, which can be optimized later.
82  * Called on each result obtained for the DHT search.
83  *
84  * @param cls closure
85  * @param exp when will this value expire
86  * @param key key of the result
87  * @param get_path path of the get request
88  * @param get_path_length lenght of @a get_path
89  * @param put_path path of the put request
90  * @param put_path_length length of the @a put_path
91  * @param type type of the result
92  * @param size number of bytes in data
93  * @param data pointer to the result data
94  */
95 static void
96 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
97                     const struct GNUNET_HashCode *key,
98                     const struct GNUNET_PeerIdentity *get_path,
99                     unsigned int get_path_length,
100                     const struct GNUNET_PeerIdentity *put_path,
101                     unsigned int put_path_length,
102                     enum GNUNET_BLOCK_Type type,
103                     size_t size,
104                     const void *data)
105 {
106   const struct GNUNET_HELLO_Message *hello = data;
107   struct CadetPeer *peer;
108
109   GCPP_try_path_from_dht (get_path,
110                           get_path_length,
111                           put_path,
112                           put_path_length);
113   if ( (size >= sizeof (struct GNUNET_HELLO_Message)) &&
114        (ntohs (hello->header.size) == size) &&
115        (size == GNUNET_HELLO_size (hello)) )
116   {
117     peer = GCP_get (&put_path[0],
118                     GNUNET_YES);
119     LOG (GNUNET_ERROR_TYPE_DEBUG,
120          "Got HELLO for %s\n",
121          GCP_2s (peer));
122     GCP_set_hello (peer,
123                    hello);
124   }
125 }
126
127
128 /**
129  * Periodically announce self id in the DHT
130  *
131  * @param cls closure
132  */
133 static void
134 announce_id (void *cls)
135 {
136   struct GNUNET_HashCode phash;
137   const struct GNUNET_HELLO_Message *hello;
138   size_t size;
139   struct GNUNET_TIME_Absolute expiration;
140   struct GNUNET_TIME_Relative next_put;
141
142   hello = GCH_get_mine ();
143   size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
144   if (0 == size)
145   {
146     expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
147                                            announce_delay);
148     announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
149   }
150   else
151   {
152     expiration = GNUNET_HELLO_get_last_expiration (hello);
153     announce_delay = GNUNET_TIME_UNIT_SECONDS;
154   }
155
156   /* Call again in id_announce_time, unless HELLO expires first,
157    * but wait at least 1s. */
158   next_put
159     = GNUNET_TIME_absolute_get_remaining (expiration);
160   next_put
161     = GNUNET_TIME_relative_min (next_put,
162                                 id_announce_time);
163   next_put
164     = GNUNET_TIME_relative_max (next_put,
165                                 GNUNET_TIME_UNIT_SECONDS);
166   announce_id_task
167     = GNUNET_SCHEDULER_add_delayed (next_put,
168                                     &announce_id,
169                                     cls);
170   GNUNET_STATISTICS_update (stats,
171                             "# DHT announce",
172                             1,
173                             GNUNET_NO);
174   memset (&phash,
175           0,
176           sizeof (phash));
177   GNUNET_memcpy (&phash,
178                  &my_full_id,
179                  sizeof (my_full_id));
180   LOG (GNUNET_ERROR_TYPE_DEBUG,
181        "Announcing my HELLO (%u bytes) in the DHT\n",
182        size);
183   GNUNET_DHT_put (dht_handle,   /* DHT handle */
184                   &phash,       /* Key to use */
185                   dht_replication_level,     /* Replication level */
186                   GNUNET_DHT_RO_RECORD_ROUTE
187                   | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
188                   GNUNET_BLOCK_TYPE_DHT_HELLO,       /* Block type */
189                   size,  /* Size of the data */
190                   (const char *) hello, /* Data itself */
191                   expiration,  /* Data expiration */
192                   NULL,         /* Continuation */
193                   NULL);        /* Continuation closure */
194 }
195
196
197 /**
198  * Initialize the DHT subsystem.
199  *
200  * @param c Configuration.
201  */
202 void
203 GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
204 {
205   LOG (GNUNET_ERROR_TYPE_DEBUG,
206        "init\n");
207   if (GNUNET_OK !=
208       GNUNET_CONFIGURATION_get_value_number (c,
209                                              "CADET",
210                                              "DHT_REPLICATION_LEVEL",
211                                              &dht_replication_level))
212   {
213     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
214                                "CADET",
215                                "DHT_REPLICATION_LEVEL",
216                                "USING DEFAULT");
217     dht_replication_level = 3;
218   }
219
220   if (GNUNET_OK !=
221       GNUNET_CONFIGURATION_get_value_time (c,
222                                            "CADET",
223                                            "ID_ANNOUNCE_TIME",
224                                            &id_announce_time))
225   {
226     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
227                                "CADET",
228                                "ID_ANNOUNCE_TIME",
229                                "MISSING");
230     GNUNET_SCHEDULER_shutdown ();
231     return;
232   }
233
234   dht_handle = GNUNET_DHT_connect (c,
235                                    64);
236   GNUNET_break (NULL != dht_handle);
237   announce_delay = GNUNET_TIME_UNIT_SECONDS;
238   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id,
239                                                NULL);
240 }
241
242
243 /**
244  * Shut down the DHT subsystem.
245  */
246 void
247 GCD_shutdown (void)
248 {
249   if (NULL != dht_handle)
250   {
251     GNUNET_DHT_disconnect (dht_handle);
252     dht_handle = NULL;
253   }
254   if (NULL != announce_id_task)
255   {
256     GNUNET_SCHEDULER_cancel (announce_id_task);
257     announce_id_task = NULL;
258   }
259 }
260
261
262 /**
263  * Search DHT for paths to @a peeR_id
264  *
265  * @param peer_id peer to search for
266  * @return handle to abort search
267  */
268 struct GCD_search_handle *
269 GCD_search (const struct GNUNET_PeerIdentity *peer_id)
270 {
271   struct GNUNET_HashCode phash;
272   struct GCD_search_handle *h;
273
274   GNUNET_STATISTICS_update (stats,
275                             "# DHT search",
276                             1,
277                             GNUNET_NO);
278   memset (&phash,
279           0,
280           sizeof (phash));
281   GNUNET_memcpy (&phash,
282                  peer_id,
283                  sizeof (*peer_id));
284
285   h = GNUNET_new (struct GCD_search_handle);
286   h->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
287                                     GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
288                                     &phash,     /* key to search */
289                                     dht_replication_level, /* replication level */
290                                     GNUNET_DHT_RO_RECORD_ROUTE |
291                                     GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
292                                     NULL,       /* xquery */
293                                     0,     /* xquery bits */
294                                     &dht_get_id_handler,
295                                     h);
296   LOG (GNUNET_ERROR_TYPE_DEBUG,
297        "Starting DHT GET for peer %s (%p)\n",
298        GNUNET_i2s (peer_id),
299        h);
300   return h;
301 }
302
303
304 /**
305  * Stop DHT search started with #GCD_search().
306  *
307  * @param h handle to search to stop
308  */
309 void
310 GCD_search_stop (struct GCD_search_handle *h)
311 {
312   LOG (GNUNET_ERROR_TYPE_DEBUG,
313        "Stopping DHT GET %p\n",
314        h);
315   GNUNET_DHT_get_stop (h->dhtget);
316   GNUNET_free (h);
317 }
318
319 /* end of gnunet-service-cadet_dht.c */