shutdown callback
[oweals/gnunet.git] / src / fs / fs_namespace.c
index 873494c4f4e184381834a4ad2507ccfdc492763c..10be6f45911aaa2d6ebb4c1aeafc99470b1fac6e 100644 (file)
@@ -79,12 +79,74 @@ struct AdvertisementContext
   struct GNUNET_DATASTORE_Handle *dsh;
 
   /**
-   * URI that was created.
+   * Our scheduler.
+   */
+  struct GNUNET_SCHEDULER_Handle *sched;
+
+  /**
+   * Our KSK URI.
    */ 
-  struct GNUNET_FS_Uri *uri;
+  struct GNUNET_FS_Uri *ksk_uri;
+
+  /**
+   * Plaintext.
+   */
+  char *pt;
+
+  /**
+   * NBlock to sign and store.
+   */
+  struct NBlock *nb;
+
+  /**
+   * The namespace.
+   */
+  struct GNUNET_FS_Namespace *ns;
+
+  /**
+   * Expiration time.
+   */
+  struct GNUNET_TIME_Absolute expiration;
+
+  /**
+   * Number of bytes of plaintext.
+   */ 
+  size_t pt_size;
+
+  /**
+   * Anonymity level.
+   */
+  uint32_t anonymity;
+
+  /**
+   * Content priority.
+   */
+  uint32_t priority;
+
+  /**
+   * Current keyword offset.
+   */
+  unsigned int pos;
 };
 
 
+/**
+ * Disconnect from the datastore.
+ * 
+ * @param cls datastore handle
+ * @param tc scheduler context
+ */
+static void
+do_disconnect (void *cls,
+              const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_DATASTORE_Handle *dsh = cls;
+
+  GNUNET_DATASTORE_disconnect (dsh, 
+                              GNUNET_NO);
+}
+
+
 /**
  * Continuation called to notify client about result of the
  * operation.
@@ -99,14 +161,81 @@ advertisement_cont (void *cls,
                    const char *msg)
 {
   struct AdvertisementContext *ac = cls;
+  const char *keyword;
+  GNUNET_HashCode key;
+  GNUNET_HashCode query;
+  struct GNUNET_CRYPTO_AesSessionKey skey;
+  struct GNUNET_CRYPTO_AesInitializationVector iv;
+  struct GNUNET_CRYPTO_RsaPrivateKey *pk;
   
   if (GNUNET_OK != success)
-    ac->cont (ac->cont_cls, NULL, msg);
-  else
-    ac->cont (ac->cont_cls, ac->uri, NULL);
-  GNUNET_DATASTORE_disconnect (ac->dsh, GNUNET_NO);
-  GNUNET_FS_uri_destroy (ac->uri);
-  GNUNET_free (ac);
+    {
+      /* error! */
+      GNUNET_SCHEDULER_add_continuation (ac->sched,
+                                        &do_disconnect,
+                                        ac->dsh,
+                                        GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+      ac->cont (ac->cont_cls, NULL, msg);
+      GNUNET_FS_uri_destroy (ac->ksk_uri);
+      GNUNET_free (ac->pt);
+      GNUNET_free (ac->nb);
+      GNUNET_FS_namespace_delete (ac->ns, GNUNET_NO);
+      GNUNET_free (ac);
+      return;
+    }
+  if (ac->pos == ac->ksk_uri->data.ksk.keywordCount)
+    {
+      /* done! */
+      GNUNET_SCHEDULER_add_continuation (ac->sched,
+                                        &do_disconnect,
+                                        ac->dsh,
+                                        GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+      ac->cont (ac->cont_cls, ac->ksk_uri, NULL);
+      GNUNET_FS_uri_destroy (ac->ksk_uri);
+      GNUNET_free (ac->pt);
+      GNUNET_free (ac->nb);
+      GNUNET_FS_namespace_delete (ac->ns, GNUNET_NO);
+      GNUNET_free (ac);
+      return;
+    }
+  keyword = ac->ksk_uri->data.ksk.keywords[ac->pos++];
+  /* first character of keyword indicates if it is
+     mandatory or not -- ignore for hashing */
+  GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
+  GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
+  GNUNET_CRYPTO_aes_encrypt (ac->pt,
+                            ac->pt_size,
+                            &skey,
+                            &iv,
+                            &ac->nb[1]);
+  GNUNET_break (GNUNET_OK == 
+               GNUNET_CRYPTO_rsa_sign (ac->ns->key,
+                                       &ac->nb->ns_purpose,
+                                       &ac->nb->ns_signature));
+  pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
+  GNUNET_assert (pk != NULL);
+  GNUNET_CRYPTO_rsa_key_get_public (pk, &ac->nb->keyspace);
+  GNUNET_CRYPTO_hash (&ac->nb->keyspace,
+                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                     &query);
+  GNUNET_break (GNUNET_OK == 
+               GNUNET_CRYPTO_rsa_sign (pk,
+                                       &ac->nb->ksk_purpose,
+                                       &ac->nb->ksk_signature));
+  GNUNET_CRYPTO_rsa_key_free (pk);
+  GNUNET_DATASTORE_put (ac->dsh,
+                       0 /* no reservation */, 
+                       &query,
+                       ac->pt_size + sizeof (struct NBlock),
+                       ac->nb,
+                       GNUNET_BLOCK_TYPE_NBLOCK,
+                       ac->priority,
+                       ac->anonymity,
+                       ac->expiration,
+                       -2, 1,
+                       GNUNET_CONSTANTS_SERVICE_TIMEOUT, 
+                       &advertisement_cont,
+                       ac);
 }
 
 
@@ -114,6 +243,7 @@ advertisement_cont (void *cls,
  * Publish an advertismement for a namespace.  
  *
  * @param h handle to the file sharing subsystem
+ * @param ksk_uri keywords to use for advertisment
  * @param namespace handle for the namespace that should be advertised
  * @param meta meta-data for the namespace advertisement
  * @param anonymity for the namespace advertismement
@@ -125,6 +255,7 @@ advertisement_cont (void *cls,
  */
 void
 GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
+                              struct GNUNET_FS_Uri *ksk_uri,
                               struct GNUNET_FS_Namespace *namespace,
                               const struct GNUNET_CONTAINER_MetaData *meta,
                               uint32_t anonymity,
@@ -138,10 +269,10 @@ GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
   size_t size;
   ssize_t mdsize;
   struct NBlock *nb;
-  char *rtgt;
   char *mdst;
   struct GNUNET_DATASTORE_Handle *dsh;
   struct AdvertisementContext *ctx;
+  char *pt;
 
   /* create advertisements */
   mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
@@ -157,11 +288,10 @@ GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
       size = MAX_NBLOCK_SIZE;
       mdsize = size - sizeof (struct NBlock) - reslen;
     }
-  nb = GNUNET_malloc (size);
-  GNUNET_CRYPTO_rsa_key_get_public (namespace->key, &nb->subspace);
-  rtgt = (char *) &nb[1];
-  memcpy (rtgt, rootEntry, reslen);
-  mdst = &rtgt[reslen];
+
+  pt = GNUNET_malloc (mdsize + reslen);
+  memcpy (pt, rootEntry, reslen);
+  mdst = &pt[reslen];
   mdsize = GNUNET_CONTAINER_meta_data_serialize (meta,
                                                 &mdst,
                                                 mdsize,
@@ -169,46 +299,43 @@ GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
   if (mdsize == -1)
     {
       GNUNET_break (0);
-      GNUNET_free (nb);
+      GNUNET_free (pt);
       cont (cont_cls, NULL, _("Failed to serialize meta data"));
       return;
     }
-  size = mdsize + sizeof (struct NBlock) + reslen;
-  nb->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
-  nb->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK);
-  GNUNET_break (GNUNET_OK == 
-               GNUNET_CRYPTO_rsa_sign (namespace->key,
-                                       &nb->purpose,
-                                       &nb->signature));
+  size = mdsize + sizeof (struct NBlock) + reslen;  
+  nb = GNUNET_malloc (size);
+  GNUNET_CRYPTO_rsa_key_get_public (namespace->key, 
+                                   &nb->subspace);
+  nb->ns_purpose.size = htonl (mdsize + reslen + 
+                           sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
+                           sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+  nb->ns_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK);
+  nb->ksk_purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
+  nb->ksk_purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG);
   dsh = GNUNET_DATASTORE_connect (h->cfg, h->sched);
   if (NULL == dsh)
     {
       GNUNET_free (nb);
+      GNUNET_free (pt);
       cont (cont_cls, NULL, _("Failed to connect to datastore service"));
       return;
-    }
+    }  
   ctx = GNUNET_malloc (sizeof (struct AdvertisementContext));
   ctx->cont = cont;
   ctx->cont_cls = cont_cls;
   ctx->dsh = dsh;
-  ctx->uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
-  ctx->uri->type = sks;
-  ctx->uri->data.sks.identifier = GNUNET_strdup ("");
-  GNUNET_CRYPTO_hash (&nb->subspace,
-                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &ctx->uri->data.sks.namespace); 
-  GNUNET_DATASTORE_put (dsh,
-                       0, 
-                       &ctx->uri->data.sks.namespace,
-                       size,
-                       nb,
-                       GNUNET_DATASTORE_BLOCKTYPE_NBLOCK,
-                       priority,
-                       anonymity,
-                       expiration,
-                       GNUNET_CONSTANTS_SERVICE_TIMEOUT, 
-                       &advertisement_cont,
-                       ctx);
+  ctx->sched = h->sched;
+  ctx->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
+  ctx->nb = nb;
+  ctx->pt = pt;
+  ctx->pt_size = mdsize + reslen;
+  ctx->ns = namespace;
+  ctx->ns->rc++;
+  ctx->anonymity = anonymity;
+  ctx->priority = priority;
+  ctx->expiration = expiration;
+  advertisement_cont (ctx, GNUNET_OK, NULL);
 }
 
 
@@ -247,6 +374,7 @@ GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
       GNUNET_free (fn);
       return NULL;
     }
+  ret->name = GNUNET_strdup (name);
   ret->filename = fn;
   return ret;
 }
@@ -279,6 +407,7 @@ GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
     {
       GNUNET_CRYPTO_rsa_key_free (namespace->key);
       GNUNET_free (namespace->filename);
+      GNUNET_free (namespace->name);
       GNUNET_free (namespace);
     }
   return GNUNET_OK;