-more work on new GNS implementation
[oweals/gnunet.git] / src / gns / gnunet-gns.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012-2013 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 gnunet-gns.c
22  * @brief command line tool to access distributed GNS
23  * @author Christian Grothoff
24  *
25  */
26 #include "platform.h"
27 #include <gnunet_util_lib.h>
28 #include <gnunet_dnsparser_lib.h>
29 #include <gnunet_namestore_service.h>
30 #include <gnunet_gns_service.h>
31
32 /**
33  * Handle to GNS service.
34  */
35 static struct GNUNET_GNS_Handle *gns;
36
37 /**
38  * GNS name to lookup. (-u option)
39  */
40 static char *lookup_name;
41
42 /**
43  * record type to look up (-t option)
44  */
45 static char *lookup_type;
46
47 /**
48  * raw output
49  */
50 static int raw;
51
52 /**
53  * Requested record type.
54  */
55 static int rtype;
56
57 /**
58  * Handle to lookup request 
59  */
60 static struct GNUNET_GNS_LookupRequest *lookup_request;
61
62
63 /**
64  * Task run on shutdown.  Cleans up everything.
65  *
66  * @param cls unused
67  * @param tc scheduler context
68  */
69 static void
70 do_shutdown (void *cls,
71              const struct GNUNET_SCHEDULER_TaskContext *tc)
72 {
73   if (NULL != lookup_request)
74   {
75     GNUNET_GNS_lookup_cancel (lookup_request);
76     lookup_request = NULL;
77   }
78   if (NULL != gns)
79   {
80     GNUNET_GNS_disconnect (gns);
81     gns = NULL;
82   }
83 }
84
85
86 /**
87  * Function called with the result of a GADS lookup.
88  *
89  * @param cls the 'const char *' name that was resolved
90  * @param rd_count number of records returned
91  * @param rd array of 'rd_count' records with the results
92  */
93 static void
94 process_lookup_result (void *cls, uint32_t rd_count,
95                        const struct GNUNET_NAMESTORE_RecordData *rd)
96 {
97   const char *name = cls;
98   uint32_t i;
99   const char *typename;
100   char* string_val;
101
102   lookup_request = NULL; 
103   if (!raw) 
104   {
105     if (0 == rd_count)
106       printf ("No results.\n");
107     else
108       printf ("%s:\n", 
109               name);
110   }
111   for (i=0; i<rd_count; i++)
112   {
113     typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
114     string_val = GNUNET_NAMESTORE_value_to_string (rd[i].record_type,
115                                                    rd[i].data,
116                                                    rd[i].data_size);
117     if (raw)
118       printf ("%s\n", 
119               string_val);
120     else
121       printf ("Got `%s' record: %s\n",
122               typename, 
123               string_val);
124     GNUNET_free_non_null (string_val);
125   }
126   GNUNET_SCHEDULER_shutdown ();
127 }
128
129
130 /**
131  * Main function that will be run.
132  *
133  * @param cls closure
134  * @param args remaining command-line arguments
135  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
136  * @param cfg configuration
137  */
138 static void
139 run (void *cls, char *const *args, const char *cfgfile,
140      const struct GNUNET_CONFIGURATION_Handle *cfg)
141 {
142   char *keyfile;
143   struct GNUNET_CRYPTO_EccPrivateKey *key;
144   struct GNUNET_CRYPTO_EccPublicKey pkey;
145   struct GNUNET_CRYPTO_EccPrivateKey *shorten_key;
146
147   gns = GNUNET_GNS_connect (cfg);
148   if (NULL == gns)
149   {
150     fprintf (stderr,
151              _("Failed to connect to GNS\n"));
152     return;
153   }
154   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
155                                                            "ZONEKEY", &keyfile))
156   {
157     fprintf (stderr,
158              "Need zone to perform lookup in!\n");
159     GNUNET_SCHEDULER_shutdown ();
160     return;
161   }
162   /* FIXME: use identity service and/or allow user to specify public key! */
163   key = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
164   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
165   GNUNET_CRYPTO_ecc_key_free (key);  
166   GNUNET_free (keyfile);
167   
168   if (GNUNET_OK != 
169       GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
170                                                "SHORTEN_ZONEKEY", &keyfile))
171   {
172     shorten_key = NULL;
173   }
174   else
175   {
176     // FIXME: use identity service!
177     shorten_key = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
178     GNUNET_free (keyfile);
179   }
180     
181   if (NULL != lookup_type)
182     rtype = GNUNET_NAMESTORE_typename_to_number (lookup_type);
183   else
184     rtype = GNUNET_DNSPARSER_TYPE_A;
185
186   if (NULL != lookup_name)
187   {
188     lookup_request = GNUNET_GNS_lookup (gns, 
189                                         lookup_name,
190                                         &pkey,
191                                         rtype,
192                                         GNUNET_NO, /* Use DHT */
193                                         shorten_key,
194                                         &process_lookup_result, 
195                                         lookup_name);
196   }
197   else
198   {
199     fprintf (stderr,
200              _("Please specify name to lookup!\n"));
201     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
202     return;
203   }
204   if (NULL != shorten_key)
205     GNUNET_CRYPTO_ecc_key_free (shorten_key);
206   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
207                                 &do_shutdown, NULL);
208 }
209
210
211 /**
212  * The main function for gnunet-gns.
213  *
214  * @param argc number of arguments from the command line
215  * @param argv command line arguments
216  * @return 0 ok, 1 on error
217  */
218 int
219 main (int argc, char *const *argv)
220 {
221   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
222     {'u', "lookup", "NAME",
223       gettext_noop ("Lookup a record for the given name"), 1,
224       &GNUNET_GETOPT_set_string, &lookup_name},
225     {'t', "type", "TYPE",
226       gettext_noop ("Specify the type of the record to lookup"), 1,
227       &GNUNET_GETOPT_set_string, &lookup_type},
228     {'r', "raw", NULL,
229       gettext_noop ("No unneeded output"), 0,
230       &GNUNET_GETOPT_set_one, &raw},
231     GNUNET_GETOPT_OPTION_END
232   };
233   int ret;
234
235   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
236     return 2;
237
238   GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
239   ret =
240       (GNUNET_OK ==
241        GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
242                            _("GNUnet GNS resolver tool"), 
243                            options,
244                            &run, NULL)) ? 0 : 1;
245   GNUNET_free ((void*) argv);
246   return ret;
247 }
248
249 /* end of gnunet-gns.c */