glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / dht / gnunet-dht-get.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 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 /**
16  * @file dht/gnunet-dht-get.c
17  * @brief search for data in DHT
18  * @author Christian Grothoff
19  * @author Nathan Evans
20  */
21 #include "platform.h"
22 #include "gnunet_dht_service.h"
23
24 #define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__)
25 /**
26  * The type of the query
27  */
28 static unsigned int query_type;
29
30 /**
31  * Desired replication level
32  */
33 static unsigned int replication = 5;
34
35 /**
36  * The key for the query
37  */
38 static char *query_key;
39
40 /**
41  * User supplied timeout value
42  */
43 static struct GNUNET_TIME_Relative timeout_request = { 60000 };
44
45 /**
46  * Be verbose
47  */
48 static unsigned int verbose;
49
50 /**
51  * Use DHT demultixplex_everywhere
52  */
53 static int demultixplex_everywhere;
54
55 /**
56  * Handle to the DHT
57  */
58 static struct GNUNET_DHT_Handle *dht_handle;
59
60 /**
61  * Global handle of the configuration
62  */
63 static const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65 /**
66  * Handle for the get request
67  */
68 static struct GNUNET_DHT_GetHandle *get_handle;
69
70 /**
71  * Count of results found
72  */
73 static unsigned int result_count;
74
75 /**
76  * Global status value
77  */
78 static int ret;
79
80 /**
81  * Task scheduled to handle timeout.
82  */
83 static struct GNUNET_SCHEDULER_Task *tt;
84
85
86 /**
87  * Task run to clean up on shutdown.
88  *
89  * @param cls unused
90  */
91 static void
92 cleanup_task (void *cls)
93 {
94   if (NULL != get_handle)
95   {
96     GNUNET_DHT_get_stop (get_handle);
97     get_handle = NULL;
98   }
99   if (NULL != dht_handle)
100   {
101     GNUNET_DHT_disconnect (dht_handle);
102     dht_handle = NULL;
103   }
104   if (NULL != tt)
105   {
106     GNUNET_SCHEDULER_cancel (tt);
107     tt = NULL;
108   }
109 }
110
111
112 /**
113  * Task run on timeout. Triggers shutdown.
114  *
115  * @param cls unused
116  */
117 static void
118 timeout_task (void *cls)
119 {
120   tt = NULL;
121   GNUNET_SCHEDULER_shutdown ();
122 }
123
124
125 /**
126  * Iterator called on each result obtained for a DHT
127  * operation that expects a reply
128  *
129  * @param cls closure
130  * @param exp when will this value expire
131  * @param key key of the result
132  * @param get_path peers on reply path (or NULL if not recorded)
133  * @param get_path_length number of entries in get_path
134  * @param put_path peers on the PUT path (or NULL if not recorded)
135  * @param put_path_length number of entries in get_path
136  * @param type type of the result
137  * @param size number of bytes in data
138  * @param data pointer to the result data
139  */
140 static void
141 get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
142                      const struct GNUNET_HashCode * key,
143                      const struct GNUNET_PeerIdentity *get_path,
144                      unsigned int get_path_length,
145                      const struct GNUNET_PeerIdentity *put_path,
146                      unsigned int put_path_length,
147                      enum GNUNET_BLOCK_Type type,
148                      size_t size,
149                      const void *data)
150 {
151   FPRINTF (stdout,
152            (GNUNET_BLOCK_TYPE_TEST == type)
153            ? _("Result %d, type %d:\n%.*s\n")
154            : _("Result %d, type %d:\n"),
155            result_count,
156            type,
157            (unsigned int) size,
158            (char *) data);
159   if (verbose)
160   {
161     FPRINTF (stdout,
162              "  GET path: ");
163     for (unsigned int i=0;i<get_path_length;i++)
164       FPRINTF (stdout,
165                "%s%s",
166                (0 == i) ? "" : "-",
167                GNUNET_i2s (&get_path[i]));
168     FPRINTF (stdout,
169              "\n  PUT path: ");
170     for (unsigned int i=0;i<put_path_length;i++)
171       FPRINTF (stdout,
172                "%s%s",
173                (0 == i) ? "" : "-",
174                GNUNET_i2s (&put_path[i]));
175     FPRINTF (stdout,
176              "\n");
177   }
178   result_count++;
179 }
180
181
182 /**
183  * Main function that will be run by the scheduler.
184  *
185  * @param cls closure
186  * @param args remaining command-line arguments
187  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
188  * @param c configuration
189  */
190 static void
191 run (void *cls, char *const *args, const char *cfgfile,
192      const struct GNUNET_CONFIGURATION_Handle *c)
193 {
194   struct GNUNET_HashCode key;
195
196   cfg = c;
197   if (NULL == query_key)
198   {
199     FPRINTF (stderr, "%s",  _("Must provide key for DHT GET!\n"));
200     ret = 1;
201     return;
202   }
203   if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1)))
204   {
205     FPRINTF (stderr, "%s",  _("Failed to connect to DHT service!\n"));
206     ret = 1;
207     return;
208   }
209   if (query_type == GNUNET_BLOCK_TYPE_ANY)      /* Type of data not set */
210     query_type = GNUNET_BLOCK_TYPE_TEST;
211   GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key);
212   if (verbose)
213     FPRINTF (stderr, "%s `%s' \n",
214              _("Issueing DHT GET with key"),
215              GNUNET_h2s_full (&key));
216   GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
217   tt = GNUNET_SCHEDULER_add_delayed (timeout_request,
218                                      &timeout_task,
219                                      NULL);
220   get_handle =
221       GNUNET_DHT_get_start (dht_handle, query_type, &key, replication,
222                             (demultixplex_everywhere) ? GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE : GNUNET_DHT_RO_NONE,
223                             NULL, 0,
224                             &get_result_iterator,
225                             NULL);
226 }
227
228
229 /**
230  * Entry point for gnunet-dht-get
231  *
232  * @param argc number of arguments from the command line
233  * @param argv command line arguments
234  * @return 0 ok, 1 on error
235  */
236 int
237 main (int argc, char *const *argv)
238 {
239   struct GNUNET_GETOPT_CommandLineOption options[] = {
240     GNUNET_GETOPT_option_string ('k',
241                                  "key",
242                                  "KEY",
243                                  gettext_noop ("the query key"),
244                                  &query_key),
245     GNUNET_GETOPT_option_uint ('r',
246                                "replication",
247                                "LEVEL",
248                                gettext_noop ("how many parallel requests (replicas) to create"),
249                                &replication),
250     GNUNET_GETOPT_option_uint ('t',
251                                "type",
252                                "TYPE",
253                                gettext_noop ("the type of data to look for"),
254                                &query_type),
255     GNUNET_GETOPT_option_relative_time ('T',
256                                         "timeout",
257                                         "TIMEOUT",
258                                         gettext_noop ("how long to execute this query before giving up?"),
259                                         &timeout_request),
260     GNUNET_GETOPT_option_flag ('x',
261                                "demultiplex",
262                                gettext_noop ("use DHT's demultiplex everywhere option"),
263                                &demultixplex_everywhere),
264     GNUNET_GETOPT_option_verbose (&verbose),
265     GNUNET_GETOPT_OPTION_END
266   };
267
268
269
270   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
271     return 2;
272   return (GNUNET_OK ==
273           GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-get",
274                               gettext_noop
275                               ("Issue a GET request to the GNUnet DHT, prints results."),
276                               options, &run, NULL)) ? ret : 1;
277 }
278
279 /* end of gnunet-dht-get.c */