-fixes
[oweals/gnunet.git] / src / gns / gnunet-service-gns.c
index 31b3822fb43715e28b7445298c0978a837ccb517..ac1067c0e5ae61d07950b78cbdc7cb4266be42b7 100644 (file)
@@ -140,10 +140,17 @@ struct GNUNET_CRYPTO_ShortHashCode zone_hash;
 /**
  * Useful for zone update for DHT put
  */
-static int num_public_records =  3600;
+static int num_public_records = 0;
+
+/**
+ * update interval in seconds
+ */
+static unsigned long long int max_record_put_interval;
+
+static unsigned long long int dht_max_update_interval;
 
 /* dht update interval FIXME define? */
-static struct GNUNET_TIME_Relative dht_update_interval;
+static struct GNUNET_TIME_Relative record_put_interval;
 
 /* zone update task */
 GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
@@ -154,6 +161,16 @@ static int auto_import_pkey;
 /* lookup timeout */
 static struct GNUNET_TIME_Relative default_lookup_timeout;
 
+/**
+ * Continue shutdown
+ */
+static void
+on_resolver_cleanup(void)
+{
+  GNUNET_NAMESTORE_disconnect(namestore_handle, 1);
+  GNUNET_DHT_disconnect(dht_handle);
+}
+
 /**
  * Task run during shutdown.
  *
@@ -173,10 +190,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_SERVER_notification_context_destroy (nc);
   
   gns_interceptor_stop();
-  gns_resolver_cleanup();
+  gns_resolver_cleanup(&on_resolver_cleanup);
 
-  GNUNET_NAMESTORE_disconnect(namestore_handle, 1);
-  GNUNET_DHT_disconnect(dht_handle);
 }
 
 
@@ -245,11 +260,11 @@ put_gns_record(void *cls,
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Zone iteration finished. Rescheduling put in %ds\n",
-               GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL);
+               dht_max_update_interval);
     zone_update_taskid = GNUNET_SCHEDULER_add_delayed (
                                         GNUNET_TIME_relative_multiply(
                                             GNUNET_TIME_UNIT_SECONDS,
-                                            GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL
+                                            dht_max_update_interval
                                             ),
                                             &update_zone_dht_start,
                                             NULL);
@@ -316,6 +331,9 @@ put_gns_record(void *cls,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "putting records for %s under key: %s with size %d\n",
              name, (char*)&xor_hash_string, rd_payload_length);
+  
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "DHT req to %d\n", DHT_OPERATION_TIMEOUT.rel_value);
 
   GNUNET_DHT_put (dht_handle, &xor_hash,
                   DHT_GNS_REPLICATION_LEVEL,
@@ -333,7 +351,7 @@ put_gns_record(void *cls,
   /**
    * Reschedule periodic put
    */
-  zone_update_taskid = GNUNET_SCHEDULER_add_delayed (dht_update_interval,
+  zone_update_taskid = GNUNET_SCHEDULER_add_delayed (record_put_interval,
                                 &update_zone_dht_next,
                                 NULL);
 
@@ -351,24 +369,32 @@ static void
 update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling DHT zone update!\n");
+  
+  unsigned long long int interval = 0;
+
   if (0 == num_public_records)
   {
-    dht_update_interval = GNUNET_TIME_relative_multiply(
+    /**
+     * If no records are known (startup) or none present
+     * we can safely set the interval to 1s
+     */
+    record_put_interval = GNUNET_TIME_relative_multiply(
                                             GNUNET_TIME_UNIT_SECONDS,
-                                            GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL);
+                                            1);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "No records in db. Adjusted DHT update interval to %ds\n",
-               GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL);
+               "No records in db. Adjusted record put interval to 1s\n");
   }
   else
   {
-    
-    dht_update_interval = GNUNET_TIME_relative_multiply(
-                                                      GNUNET_TIME_UNIT_SECONDS,
-                                                     (3600/num_public_records));
+    interval = max_record_put_interval/num_public_records;
+    if (interval == 0)
+      interval = 1;
+    record_put_interval = GNUNET_TIME_relative_multiply(
+                                  GNUNET_TIME_UNIT_SECONDS,
+                                  interval);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Adjusted DHT update interval to %ds!\n",
-               (3600/num_public_records));
+               interval);
   }
 
   /* start counting again */
@@ -440,7 +466,8 @@ static void handle_shorten(void *cls,
 
   size_t msg_size = 0;
   struct ClientShortenHandle *csh;
-  const char* name;
+  char name[MAX_DNS_NAME_LENGTH];
+  char* nameptr = name;
 
   if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage))
   {
@@ -449,7 +476,6 @@ static void handle_shorten(void *cls,
     return;
   }
 
-  GNUNET_SERVER_notification_context_add (nc, client);
 
   struct GNUNET_GNS_ClientShortenMessage *sh_msg =
     (struct GNUNET_GNS_ClientShortenMessage *) message;
@@ -467,16 +493,25 @@ static void handle_shorten(void *cls,
   csh->client = client;
   csh->unique_id = sh_msg->id;
   
-  name = (char*)&sh_msg[1];
+  GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
 
   if (strlen (name) < strlen(GNUNET_GNS_TLD)) {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "SHORTEN: %s is too short", name);
+    csh->name = NULL;
+    send_shorten_response(csh, name);
+    return;
+  }
+
+  if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "SHORTEN: %s is too long", name);
     csh->name = NULL;
     send_shorten_response(csh, name);
     return;
   }
   
-  if (strcmp(name+strlen(name)-strlen(GNUNET_GNS_TLD),
-             GNUNET_GNS_TLD) != 0)
+  if (!is_gnunet_tld(name) && !is_zkey_tld(name))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "%s is not our domain. Returning\n", name);
@@ -485,15 +520,15 @@ static void handle_shorten(void *cls,
     return;
   }
   
-  csh->name = GNUNET_malloc(strlen(name)
-                            - strlen(GNUNET_GNS_TLD) + 1);
-  memset(csh->name, 0,
-         strlen(name)-strlen(GNUNET_GNS_TLD) + 1);
-  memcpy(csh->name, name,
-         strlen(name)-strlen(GNUNET_GNS_TLD));
-
+  GNUNET_SERVER_notification_context_add (nc, client);
+  
   /* Start shortening */
-  gns_resolver_shorten_name(zone_hash, name, &send_shorten_response, csh);
+  if (GNUNET_YES == auto_import_pkey)
+    gns_resolver_shorten_name(zone_hash, name, zone_key,
+                              &send_shorten_response, csh);
+  else
+    gns_resolver_shorten_name(zone_hash, name, NULL,
+                              &send_shorten_response, csh);
 }
 
 
@@ -558,7 +593,9 @@ static void handle_get_authority(void *cls,
 
   size_t msg_size = 0;
   struct ClientGetAuthHandle *cah;
-  const char* name;
+  char name[MAX_DNS_NAME_LENGTH];
+  char* nameptr = name;
+
 
   if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage))
   {
@@ -581,7 +618,8 @@ static void handle_get_authority(void *cls,
     return;
   }
   
-  name = (char*)&sh_msg[1];
+  GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
+
 
   cah = GNUNET_malloc(sizeof(struct ClientGetAuthHandle));
   cah->client = client;
@@ -590,17 +628,25 @@ static void handle_get_authority(void *cls,
   if (strlen(name) < strlen(GNUNET_GNS_TLD))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s is too short. Returning\n", name);
+                "GET_AUTH: %s is too short. Returning\n", name);
     cah->name = NULL;
     send_get_auth_response(cah, name);
     return;
   }
-
+  
+  if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GET_AUTH: %s is too long", name);
+    cah->name = NULL;
+    send_get_auth_response(cah, name);
+    return;
+  }
+  
   if (strcmp(name+strlen(name)-strlen(GNUNET_GNS_TLD),
              GNUNET_GNS_TLD) != 0)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s is not our domain. Returning\n", name);
+                "GET_AUTH: %s is not our domain. Returning\n", name);
     cah->name = NULL;
     send_get_auth_response(cah, name);
     return;
@@ -609,7 +655,7 @@ static void handle_get_authority(void *cls,
   if (strcmp(name, GNUNET_GNS_TLD) == 0)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s is us. Returning\n", name);
+                "GET_AUTH: %s is us. Returning\n", name);
     cah->name = NULL;
     send_get_auth_response(cah, name);
     return;
@@ -685,8 +731,9 @@ handle_lookup(void *cls,
 
   size_t msg_size = 0;
   size_t namelen;
-  char* name;
+  char name[MAX_DNS_NAME_LENGTH];
   struct ClientLookupHandle *clh;
+  char* nameptr = name;
 
   if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientLookupMessage))
   {
@@ -709,7 +756,7 @@ handle_lookup(void *cls,
     return;
   }
   
-  name = (char*)&sh_msg[1];
+  GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
   namelen = strlen(name)+1;
   clh = GNUNET_malloc(sizeof(struct ClientLookupHandle));
   clh->client = client;
@@ -718,6 +765,14 @@ handle_lookup(void *cls,
   clh->unique_id = sh_msg->id;
   clh->type = ntohl(sh_msg->type);
   
+  if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "LOOKUP: %s is too long", name);
+    clh->name = NULL;
+    send_lookup_response(clh, 0, NULL);
+    return;
+  }
+  
   if (GNUNET_YES == auto_import_pkey)
   {
     gns_resolver_lookup_record(zone_hash, clh->type, name,
@@ -754,6 +809,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
   unsigned long long max_parallel_bg_queries = 0;
   unsigned long long default_lookup_timeout_secs = 0;
+  int ignore_pending = GNUNET_NO;
 
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     {&handle_shorten, NULL, GNUNET_MESSAGE_TYPE_GNS_SHORTEN, 0},
@@ -795,15 +851,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
     return;
   }
   
-  /**
-   * handle to the dht
-   */
-  dht_handle = GNUNET_DHT_connect(c, 1); //FIXME get ht_len from cfg
+  
 
-  if (NULL == dht_handle)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n");
-  }
+  auto_import_pkey = GNUNET_NO;
 
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
@@ -815,8 +865,32 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
 
   }
 
+  dht_max_update_interval = GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL;
+
   if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_number(c, "gns",
+      GNUNET_CONFIGURATION_get_value_number (c, "gns",
+                                             "ZONE_PUT_INTERVAL",
+                                             &dht_max_update_interval))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+               "DHT zone update interval: %d\n",
+               dht_max_update_interval);
+  }
+  
+  max_record_put_interval = 1;
+
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_number (c, "gns",
+                                             "RECORD_PUT_INTERVAL",
+                                             &max_record_put_interval))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+               "Record put interval: %d\n",
+               max_record_put_interval);
+  }
+  
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_number (c, "gns",
                                             "MAX_PARALLEL_BACKGROUND_QUERIES",
                                             &max_parallel_bg_queries))
   {
@@ -825,6 +899,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
                max_parallel_bg_queries);
   }
 
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
+                                            "AUTO_IMPORT_CONFIRMATION_REQ"))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+               "Auto import requires user confirmation\n");
+    ignore_pending = GNUNET_YES;
+  }
+
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_number(c, "gns",
                                             "DEFAULT_LOOKUP_TIMEOUT",
@@ -837,8 +920,21 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
                                             default_lookup_timeout_secs);
   }
   
+  /**
+   * handle to the dht
+   */
+  dht_handle = GNUNET_DHT_connect(c,
+                       //max_parallel_bg_queries); //FIXME get ht_len from cfg
+                       1024);
+
+  if (NULL == dht_handle)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n");
+  }
+  
   if (gns_resolver_init(namestore_handle, dht_handle, zone_hash,
-                        max_parallel_bg_queries)
+                        max_parallel_bg_queries,
+                        ignore_pending)
       == GNUNET_SYSERR)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
@@ -848,8 +944,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
   }
 
   if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
-                                            "HIJACK_DNS"))
+      GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS"))
   {
     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
                "DNS hijacking enabled... connecting to service.\n");
@@ -861,14 +956,12 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
     }
   }
   
-  //put_some_records(); //FIXME for testing
-  
   /**
    * Schedule periodic put
    * for our records
    * We have roughly an hour for all records;
    */
-  dht_update_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
+  record_put_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
                                                       1);
   zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start, NULL);