RECLAIM: refactoring; cleanup
[oweals/gnunet.git] / src / gns / gnunet-gns.c
index bb256dadf0df554e3e69088fd0502b89490edb5d..83dd7b27b5f32efbbbf8d9e75ac8de01fb9cd7f0 100644 (file)
@@ -1,79 +1,93 @@
 /*
      This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2012-2013, 2017-2018 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 /**
  * @file gnunet-gns.c
  * @brief command line tool to access distributed GNS
  * @author Christian Grothoff
- *
- * TODO:
- * - everything
  */
 #include "platform.h"
 #include <gnunet_util_lib.h>
 #include <gnunet_dnsparser_lib.h>
+#include <gnunet_gnsrecord_lib.h>
 #include <gnunet_namestore_service.h>
 #include <gnunet_gns_service.h>
 
 /**
- * Handle to GNS service.
+ * Configuration we are using.
  */
-static struct GNUNET_GNS_Handle *gns;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 /**
- * GNS name to shorten. (-s option)
+ * Handle to GNS service.
  */
-static char *shorten_name;
+static struct GNUNET_GNS_Handle *gns;
 
 /**
  * GNS name to lookup. (-u option)
  */
 static char *lookup_name;
 
-
 /**
  * record type to look up (-t option)
  */
 static char *lookup_type;
 
 /**
- * name to look up authority for (-a option)
+ * raw output
  */
-static char *auth_name;
+static int raw;
 
 /**
- * raw output
+ * Desired record type.
+ */
+static uint32_t rtype;
+
+/**
+ * Handle to lookup request
+ */
+static struct GNUNET_GNS_LookupWithTldRequest *lr;
+
+/**
+ * Global return value.
+ * 0 on success (default),
+ * 1 on internal failures
+ * 2 on launch failure,
+ * 4 if the name is not a GNS-supported TLD,
  */
-static int raw = 0;
+static int global_ret;
 
-static enum GNUNET_GNS_RecordType rtype;
 
 /**
  * Task run on shutdown.  Cleans up everything.
  *
  * @param cls unused
- * @param tc scheduler context
  */
 static void
-do_shutdown (void *cls,
-            const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_shutdown (void *cls)
 {
+  (void) cls;
+  if (NULL != lr)
+  {
+    GNUNET_GNS_lookup_with_tld_cancel (lr);
+    lr = NULL;
+  }
   if (NULL != gns)
   {
     GNUNET_GNS_disconnect (gns);
@@ -82,53 +96,68 @@ do_shutdown (void *cls,
 }
 
 
+/**
+ * Function called with the result of a GNS lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param was_gns #GNUNET_NO if TLD did not indicate use of GNS
+ * @param rd_count number of records returned
+ * @param rd array of @a rd_count records with the results
+ */
 static void
-process_shorten_result(void* cls, const char* nshort)
-{
-  printf("%s shortened to %s\n", (char*) cls, nshort);
-  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
-
-static void
-process_lookup_result(void* cls, uint32_t rd_count,
-                      const struct GNUNET_NAMESTORE_RecordData *rd)
+process_lookup_result (void *cls,
+                      int was_gns,
+                       uint32_t rd_count,
+                      const struct GNUNET_GNSRECORD_Data *rd)
 {
-  int i;
-  char* name = (char*) cls;
-  const char* typename;
+  const char *name = cls;
+  const char *typename;
   char* string_val;
-  
-  if (!raw) {
-    if (rd_count == 0)
-      printf("No results.\n");
+
+  lr = NULL;
+  if (GNUNET_NO == was_gns)
+  {
+    global_ret = 4; /* not for GNS */
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (! raw)
+  {
+    if (0 == rd_count)
+      printf ("No results.\n");
     else
-      printf("%s:\n", name);
+      printf ("%s:\n",
+             name);
   }
-
-
-
-  for (i=0; i<rd_count; i++)
+  for (uint32_t i=0; i<rd_count; i++)
   {
-    typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
-    string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
-                                                  rd[i].data,
-                                                  rd[i].data_size);
+    if ( (rd[i].record_type != rtype) &&
+        (GNUNET_GNSRECORD_TYPE_ANY != rtype) )
+      continue;
+    typename = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
+    string_val = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                                  rd[i].data,
+                                                  rd[i].data_size);
+    if (NULL == string_val)
+    {
+      fprintf (stderr,
+              "Record %u of type %d malformed, skipping\n",
+              (unsigned int) i,
+              (int) rd[i].record_type);
+      continue;
+    }
     if (raw)
-      printf("%s\n", string_val);
+      printf ("%s\n",
+             string_val);
     else
-      printf("Got %s record: %s\n", typename, string_val);
-
+      printf ("Got `%s' record: %s\n",
+             typename,
+             string_val);
+    GNUNET_free (string_val);
   }
-
-  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+  GNUNET_SCHEDULER_shutdown ();
 }
 
-static void
-process_auth_result(void* cls, const char* auth)
-{
-  printf ("%s\n", auth);
-  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
-}
 
 /**
  * Main function that will be run.
@@ -136,82 +165,52 @@ process_auth_result(void* cls, const char* auth)
  * @param cls closure
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param cfg configuration
+ * @param c configuration
  */
 static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  char* keyfile;
-  struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
-  struct GNUNET_CRYPTO_ShortHashCode *zone = NULL;
-  struct GNUNET_CRYPTO_ShortHashCode user_zone;
-  struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename;
-
-  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
-                                                           "ZONEKEY", &keyfile))
-  {
-    if (!raw)
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "No private key for root zone found, using default!\n");
-    zone = NULL;
-  }
-  else
-  {
-    if (GNUNET_YES == GNUNET_DISK_file_test (keyfile))
-    {
-      key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
-      GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
-      GNUNET_CRYPTO_short_hash(&pkey,
-                         sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                         &user_zone);
-      zone = &user_zone;
-      GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename);
-      printf("asdsad\n");
-      if (!raw)
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Using zone: %s!\n", &zonename);
-      GNUNET_CRYPTO_rsa_key_free(key);
-    }
-    GNUNET_free(keyfile);
-  }
+  (void) cls;
+  (void) args;
+  (void) cfgfile;
 
+  cfg = c;
   gns = GNUNET_GNS_connect (cfg);
-  if (lookup_type != NULL)
-    rtype = GNUNET_NAMESTORE_typename_to_number(lookup_type);
-  else
-    rtype = GNUNET_GNS_RECORD_TYPE_A;
-
   if (NULL == gns)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Failed to connect to GNS\n"));
+    fprintf (stderr,
+            _("Failed to connect to GNS\n"));
+    global_ret = 2;
     return;
   }
-  
-  if (shorten_name != NULL)
-  {
-    /** shorten name */
-    GNUNET_GNS_shorten_zone (gns, shorten_name, zone, &process_shorten_result,
-                       shorten_name);
-  }
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 NULL);
 
-  if (lookup_name != NULL)
+  if (NULL != lookup_type)
+    rtype = GNUNET_GNSRECORD_typename_to_number (lookup_type);
+  else
+    rtype = GNUNET_DNSPARSER_TYPE_A;
+  if (UINT32_MAX == rtype)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Lookup\n");
-    GNUNET_GNS_lookup_zone (gns, lookup_name, zone, rtype,
-                      &process_lookup_result, lookup_name);
+    fprintf (stderr,
+             _("Invalid typename specified, assuming `ANY'\n"));
+    rtype = GNUNET_GNSRECORD_TYPE_ANY;
   }
-
-  if (auth_name != NULL)
+  lr = GNUNET_GNS_lookup_with_tld (gns,
+                                  lookup_name,
+                                  rtype,
+                                  GNUNET_GNS_LO_DEFAULT,
+                                  &process_lookup_result,
+                                  lookup_name);
+  if (NULL == lr)
   {
-    GNUNET_GNS_get_authority(gns, auth_name, &process_auth_result, auth_name);
+    global_ret = 2;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
   }
-  
-  // FIXME: do work here...
-  //GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
 }
 
 
@@ -223,38 +222,46 @@ run (void *cls, char *const *args, const char *cfgfile,
  * @return 0 ok, 1 on error
  */
 int
-main (int argc, char *const *argv)
+main (int argc,
+      char *const *argv)
 {
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'s', "shorten", NULL,
-     gettext_noop ("try to shorten a given GNS name"), 1,
-     &GNUNET_GETOPT_set_string, &shorten_name},
-    {'u', "lookup", NULL,
-      gettext_noop ("Lookup a record using GNS (NOT IMPLEMENTED)"), 1,
-      &GNUNET_GETOPT_set_string, &lookup_name},
-    {'a', "authority", NULL,
-      gettext_noop ("Get the authority of a particular name"), 1,
-      &GNUNET_GETOPT_set_string, &auth_name},
-    {'t', "type", NULL,
-      gettext_noop ("Specify the type of the record lookup"), 1,
-      &GNUNET_GETOPT_set_string, &lookup_type},
-    {'r', "raw", NULL,
-      gettext_noop ("No unneeded output"), 0,
-      &GNUNET_GETOPT_set_one, &raw},
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_mandatory
+    (GNUNET_GETOPT_option_string ('u',
+                                  "lookup",
+                                  "NAME",
+                                  gettext_noop ("Lookup a record for the given name"),
+                                  &lookup_name)),
+    GNUNET_GETOPT_option_string ('t',
+                                 "type",
+                                 "TYPE",
+                                 gettext_noop ("Specify the type of the record to lookup"),
+                                 &lookup_type),
+    GNUNET_GETOPT_option_flag ('r',
+                               "raw",
+                               gettext_noop ("No unneeded output"),
+                               &raw),
     GNUNET_GETOPT_OPTION_END
   };
-
   int ret;
 
-  GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
-  ret =
-      (GNUNET_OK ==
-       GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
-                           _("GNUnet GNS access tool"), 
-                          options,
-                           &run, NULL)) ? 0 : 1;
-
-  return ret;
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                    &argc, &argv))
+    return 2;
+
+  GNUNET_log_setup ("gnunet-gns",
+                    "WARNING",
+                    NULL);
+  ret = GNUNET_PROGRAM_run (argc, argv,
+                            "gnunet-gns",
+                            _("GNUnet GNS resolver tool"),
+                            options,
+                            &run, NULL);
+  GNUNET_free ((void*) argv);
+  if (GNUNET_OK != ret)
+    return 1;
+  return global_ret;
 }
 
 /* end of gnunet-gns.c */