b08521c7be337d1c3311c630efc3758acae2923a
[oweals/gnunet.git] / src / dht / gnunet-dht-monitor.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file dht/gnunet-dht-monitor.c
20  * @brief search for data in DHT
21  * @author Christian Grothoff
22  * @author Bartlomiej Polot
23  */
24 #include "platform.h"
25 #include "gnunet_dht_service.h"
26
27 /**
28  * The type of the query
29  */
30 static unsigned int block_type;
31
32 /**
33  * The key to be monitored
34  */
35 static char *query_key;
36
37 /**
38  * User supplied timeout value (in seconds)
39  */
40 static struct GNUNET_TIME_Relative timeout_request = { 60000 };
41
42 /**
43  * Be verbose
44  */
45 static int verbose;
46
47 /**
48 * Handle to the DHT
49  */
50 static struct GNUNET_DHT_Handle *dht_handle;
51
52 /**
53  * Global handle of the configuration
54  */
55 static const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57 /**
58  * Handle for the get request
59  */
60 static struct GNUNET_DHT_MonitorHandle *monitor_handle;
61
62 /**
63  * Count of messages received
64  */
65 static unsigned int result_count;
66
67 /**
68  * Global status value
69  */
70 static int ret;
71
72 /**
73  * Task scheduled to handle timeout.
74  */
75 static struct GNUNET_SCHEDULER_Task *tt;
76
77
78 /**
79  * Stop monitoring request and start shutdown
80  *
81  * @param cls closure (unused)
82  */
83 static void
84 cleanup_task (void *cls)
85 {
86   if (verbose)
87     FPRINTF (stderr, "%s",  "Cleaning up!\n");
88   if (NULL != monitor_handle)
89   {
90     GNUNET_DHT_monitor_stop (monitor_handle);
91     monitor_handle = NULL;
92   }
93   if (NULL != dht_handle)
94   {
95     GNUNET_DHT_disconnect (dht_handle);
96     dht_handle = NULL;
97   }
98   if (NULL != tt)
99   {
100     GNUNET_SCHEDULER_cancel (tt);
101     tt = NULL;
102   }
103 }
104
105
106 /**
107  * We hit a timeout. Stop monitoring request and start shutdown
108  *
109  * @param cls closure (unused)
110  */
111 static void
112 timeout_task (void *cls)
113 {
114   tt = NULL;
115   GNUNET_SCHEDULER_shutdown ();
116 }
117
118
119
120 /**
121  * Callback called on each GET request going through the DHT.
122  *
123  * @param cls Closure.
124  * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
125  * @param type The type of data in the request.
126  * @param hop_count Hop count so far.
127  * @param path_length number of entries in path (or 0 if not recorded).
128  * @param path peers on the GET path (or NULL if not recorded).
129  * @param desired_replication_level Desired replication level.
130  * @param key Key of the requested data.
131  */
132 static void
133 get_callback (void *cls,
134               enum GNUNET_DHT_RouteOption options,
135               enum GNUNET_BLOCK_Type type,
136               uint32_t hop_count,
137               uint32_t desired_replication_level,
138               unsigned int path_length,
139               const struct GNUNET_PeerIdentity *path,
140               const struct GNUNET_HashCode * key)
141 {
142   FPRINTF (stdout,
143            "GET #%u: type %d, key `%s'\n",
144            result_count,
145            (int) type,
146            GNUNET_h2s_full(key));
147   result_count++;
148 }
149
150
151 /**
152  * Callback called on each GET reply going through the DHT.
153  *
154  * @param cls Closure.
155  * @param type The type of data in the result.
156  * @param get_path Peers on GET path (or NULL if not recorded).
157  * @param get_path_length number of entries in get_path.
158  * @param put_path peers on the PUT path (or NULL if not recorded).
159  * @param put_path_length number of entries in get_path.
160  * @param exp Expiration time of the data.
161  * @param key Key of the data.
162  * @param data Pointer to the result data.
163  * @param size Number of bytes in data.
164  */
165 static void
166 get_resp_callback (void *cls,
167                    enum GNUNET_BLOCK_Type type,
168                    const struct GNUNET_PeerIdentity *get_path,
169                    unsigned int get_path_length,
170                    const struct GNUNET_PeerIdentity *put_path,
171                    unsigned int put_path_length,
172                    struct GNUNET_TIME_Absolute exp,
173                    const struct GNUNET_HashCode * key,
174                    const void *data,
175                    size_t size)
176 {
177   FPRINTF (stdout,
178            (GNUNET_BLOCK_TYPE_TEST == type)
179            ? "RESPONSE #%u (%s): type %d, key `%s', data `%.*s'\n"
180            : "RESPONSE #%u (%s): type %d, key `%s'\n",
181            result_count,
182            GNUNET_STRINGS_absolute_time_to_string (exp),
183            (int) type,
184            GNUNET_h2s_full (key),
185            (unsigned int) size,
186            (char *) data);
187   result_count++;
188 }
189
190
191 /**
192  * Callback called on each PUT request going through the DHT.
193  *
194  * @param cls Closure.
195  * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
196  * @param type The type of data in the request.
197  * @param hop_count Hop count so far.
198  * @param path_length number of entries in path (or 0 if not recorded).
199  * @param path peers on the PUT path (or NULL if not recorded).
200  * @param desired_replication_level Desired replication level.
201  * @param exp Expiration time of the data.
202  * @param key Key under which data is to be stored.
203  * @param data Pointer to the data carried.
204  * @param size Number of bytes in data.
205  */
206 static void
207 put_callback (void *cls,
208               enum GNUNET_DHT_RouteOption options,
209               enum GNUNET_BLOCK_Type type,
210               uint32_t hop_count,
211               uint32_t desired_replication_level,
212               unsigned int path_length,
213               const struct GNUNET_PeerIdentity *path,
214               struct GNUNET_TIME_Absolute exp,
215               const struct GNUNET_HashCode * key,
216               const void *data,
217               size_t size)
218 {
219   FPRINTF (stdout,
220            (GNUNET_BLOCK_TYPE_TEST == type)
221            ? "PUT %u (%s): type %d, key `%s', data `%.*s'\n"
222            : "PUT %u (%s): type %d, key `%s'\n",
223            result_count,
224            GNUNET_STRINGS_absolute_time_to_string (exp),
225            (int) type,
226            GNUNET_h2s_full(key),
227            (unsigned int) size,
228            (char *) data);
229   result_count++;
230 }
231
232
233 /**
234  * Main function that will be run by the scheduler.
235  *
236  * @param cls closure
237  * @param args remaining command-line arguments
238  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
239  * @param c configuration
240  */
241 static void
242 run (void *cls,
243      char *const *args,
244      const char *cfgfile,
245      const struct GNUNET_CONFIGURATION_Handle *c)
246 {
247   struct GNUNET_HashCode *key;
248   struct GNUNET_HashCode hc;
249
250   cfg = c;
251
252   if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1)))
253   {
254     FPRINTF (stderr, "%s",
255              _("Failed to connect to DHT service!\n"));
256     ret = 1;
257     return;
258   }
259   if (GNUNET_BLOCK_TYPE_ANY == block_type)      /* Type of data not set */
260     block_type = GNUNET_BLOCK_TYPE_TEST;
261   if (NULL != query_key)
262     {
263       key = &hc;
264       if (GNUNET_OK !=
265           GNUNET_CRYPTO_hash_from_string (query_key, key))
266         GNUNET_CRYPTO_hash (query_key, strlen (query_key), key);
267     }
268   else
269     {
270       key = NULL;
271     }
272   if (verbose)
273     FPRINTF (stderr,
274              "Monitoring for %s\n",
275              GNUNET_STRINGS_relative_time_to_string (timeout_request, GNUNET_NO));
276   tt = GNUNET_SCHEDULER_add_delayed (timeout_request,
277                                      &timeout_task,
278                                      NULL);
279   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
280                                 NULL);
281   monitor_handle = GNUNET_DHT_monitor_start (dht_handle,
282                                              block_type,
283                                              key,
284                                              &get_callback,
285                                              &get_resp_callback,
286                                              &put_callback,
287                                              NULL);
288 }
289
290 /**
291  * Entry point for gnunet-dht-monitor
292  *
293  * @param argc number of arguments from the command line
294  * @param argv command line arguments
295  * @return 0 ok, 1 on error
296  */
297 int
298 main (int argc, char *const *argv)
299 {
300   struct GNUNET_GETOPT_CommandLineOption options[] = {
301
302     GNUNET_GETOPT_option_string ('k',
303                                  "key",
304                                  "KEY",
305                                  gettext_noop ("the query key"),
306                                  &query_key),
307
308     GNUNET_GETOPT_option_uint ('t',
309                                    "type",
310                                    "TYPE",
311                                    gettext_noop ("the type of data to look for"),
312                                    &block_type),
313
314     GNUNET_GETOPT_option_relative_time ('T',
315                                             "timeout",
316                                             "TIMEOUT",
317                                             gettext_noop ("how long should the monitor command run"),
318                                             &timeout_request),
319
320     GNUNET_GETOPT_option_flag ('V',
321                                   "verbose",
322                                   gettext_noop ("be verbose (print progress information)"),
323                                   &verbose),
324
325     GNUNET_GETOPT_OPTION_END
326   };
327
328
329   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
330     return 2;
331
332   return (GNUNET_OK ==
333           GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-monitor",
334                               gettext_noop
335                               ("Prints all packets that go through the DHT."),
336                               options, &run, NULL)) ? ret : 1;
337 }
338
339 /* end of gnunet-dht-monitor.c */