8d318efc2ed17528403f3fade73241771e2c450f
[oweals/gnunet.git] / src / dht / gnunet-dht-get-peer.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file dht/gnunet-dht-get-peer.c
22  * @brief search for peers close to key using the DHT
23  * @author Christian Grothoff
24  * @author Nathan Evans
25  */
26 #include "platform.h"
27 #include "gnunet_dht_service.h"
28 #include "gnunet_hello_lib.h"
29
30 /**
31  * The key for the query
32  */
33 static char *query_key;
34
35 /**
36  * User supplied timeout value (in seconds)
37  */
38 static unsigned long long timeout_request = 5;
39
40 /**
41  * When this request should really die
42  */
43 struct GNUNET_TIME_Absolute absolute_timeout;
44
45 /**
46  * Be verbose
47  */
48 static int verbose;
49
50 /**
51  * Handle to the DHT
52  */
53 static struct GNUNET_DHT_Handle *dht_handle;
54
55
56 /**
57  * Global handle of the configuration
58  */
59 static const struct GNUNET_CONFIGURATION_Handle *cfg;
60
61 /**
62  * Handle for the request
63  */
64 static struct GNUNET_DHT_FindPeerHandle *find_peer_handle;
65
66 /**
67  * Count of results found
68  */
69 static unsigned int result_count;
70
71 /**
72  * Global status value
73  */
74 static int ret;
75
76 static void
77 shutdown_task (void *cls,
78                const struct GNUNET_SCHEDULER_TaskContext *tc)
79 {
80   if (dht_handle != NULL)
81     {
82       GNUNET_DHT_disconnect (dht_handle);
83       dht_handle = NULL;
84     }
85   fprintf (stderr,
86            _("Found %u peers\n"),
87            result_count);
88 }
89
90
91 static void
92 cleanup_task (void *cls, 
93               const struct GNUNET_SCHEDULER_TaskContext *tc)
94 {
95   if (find_peer_handle != NULL)
96     {
97       GNUNET_DHT_find_peer_stop (find_peer_handle);
98       find_peer_handle = NULL;
99     }
100   GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
101 }
102
103 /**
104  * Iterator called on each result obtained from a find peer
105  * operation
106  *
107  * @param cls closure (NULL)
108  * @param hello the response message, a HELLO
109  */
110 static void 
111 find_peer_processor (void *cls,
112                      const struct GNUNET_HELLO_Message *hello)
113 {
114   struct GNUNET_PeerIdentity peer;
115
116   if (GNUNET_OK == GNUNET_HELLO_get_id(hello, &peer))
117     {
118       result_count++;
119       if (verbose)
120         fprintf (stderr,
121                  _("Found peer `%s'\n"),
122                  GNUNET_i2s (&peer));
123     }
124 }
125
126
127 /**
128  * Main function that will be run by the scheduler.
129  *
130  * @param cls closure
131  * @param args remaining command-line arguments
132  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
133  * @param c configuration
134  */
135 static void
136 run (void *cls,
137      char *const *args,
138      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
139 {
140   struct GNUNET_TIME_Relative timeout;
141   GNUNET_HashCode key;
142   cfg = c;
143
144   if (query_key == NULL)
145     {
146       if (verbose)
147         fprintf (stderr, "Must provide key for DHT GET!\n");
148       ret = 1;
149       return;
150     }
151
152   dht_handle = GNUNET_DHT_connect (cfg, 1);
153
154   if (dht_handle == NULL)
155     {
156       if (verbose)
157         fprintf (stderr, "Couldn't connect to DHT service!\n");
158       ret = 1;
159       return;
160     }
161   else if (verbose)
162     fprintf (stderr, "Connected to DHT service!\n");
163
164   GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key);
165
166   timeout =
167     GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, timeout_request);
168   absolute_timeout = GNUNET_TIME_relative_to_absolute (timeout);
169
170   if (verbose)
171     fprintf (stderr, "Issuing FIND PEER request for %s!\n", query_key);
172
173   find_peer_handle = GNUNET_DHT_find_peer_start (dht_handle,
174                                                  timeout,
175                                                  &key,
176                                                  GNUNET_DHT_RO_NONE,
177                                                  &find_peer_processor,
178                                                  NULL);
179   if (NULL == find_peer_handle)
180     {
181       GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
182       return;
183     }
184   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
185                                 (absolute_timeout),
186                                 &cleanup_task, NULL);
187 }
188
189
190 /**
191  * gnunet-dht-get command line options
192  */
193 static struct GNUNET_GETOPT_CommandLineOption options[] = {
194   {'k', "key", "KEY",
195    gettext_noop ("the query key"),
196    1, &GNUNET_GETOPT_set_string, &query_key},
197   {'T', "timeout", "TIMEOUT",
198    gettext_noop ("how long to execute this query before giving up?"),
199    1, &GNUNET_GETOPT_set_ulong, &timeout_request},
200   {'V', "verbose", NULL,
201    gettext_noop ("be verbose (print progress information)"),
202    0, &GNUNET_GETOPT_set_one, &verbose},
203   GNUNET_GETOPT_OPTION_END
204 };
205
206
207 /**
208  * Entry point for gnunet-dht-get-peer
209  *
210  * @param argc number of arguments from the command line
211  * @param argv command line arguments
212  * @return 0 ok, 1 on error
213  */
214 int
215 main (int argc, char *const *argv)
216 {
217   return (GNUNET_OK ==
218           GNUNET_PROGRAM_run (argc,
219                               argv,
220                               "gnunet-dht-get-peer",
221                               gettext_noop
222                               ("Issue a GET PEER request to the GNUnet DHT, print results."),
223                               options, &run, NULL)) ? ret : 1;
224 }
225
226 /* end of gnunet-dht-get-peer */