+ struct GNUNET_FS_PublishSksContext *psc;
+ struct GNUNET_CRYPTO_AesSessionKey sk;
+ struct GNUNET_CRYPTO_AesInitializationVector iv;
+ struct GNUNET_FS_Uri *sks_uri;
+ char *uris;
+ size_t size;
+ size_t slen;
+ size_t nidlen;
+ size_t idlen;
+ ssize_t mdsize;
+ struct SBlock *sb;
+ struct SBlock *sb_enc;
+ char *dest;
+ struct GNUNET_CONTAINER_MetaData *mmeta;
+ GNUNET_HashCode key; /* hash of thisId = key */
+ GNUNET_HashCode id; /* hash of hc = identifier */
+ GNUNET_HashCode query; /* id ^ nsid = DB query */
+
+ if (NULL == meta)
+ mmeta = GNUNET_CONTAINER_meta_data_create ();
+ else
+ mmeta = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ uris = GNUNET_FS_uri_to_string (uri);
+ slen = strlen (uris) + 1;
+ idlen = strlen (identifier);
+ if (update != NULL)
+ nidlen = strlen (update) + 1;
+ else
+ nidlen = 1;
+ mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (mmeta);
+ size = sizeof (struct SBlock) + slen + nidlen + mdsize;
+ if (size > MAX_SBLOCK_SIZE)
+ {
+ size = MAX_SBLOCK_SIZE;
+ mdsize = size - (sizeof (struct SBlock) + slen + nidlen);
+ }
+ sb = GNUNET_malloc (sizeof (struct SBlock) + size);
+ dest = (char *) &sb[1];
+ if (update != NULL)
+ memcpy (dest, update, nidlen);
+ else
+ memset (dest, 0, 1);
+ dest += nidlen;
+ memcpy (dest, uris, slen);
+ GNUNET_free (uris);
+ dest += slen;
+ mdsize =
+ GNUNET_CONTAINER_meta_data_serialize (mmeta, &dest, mdsize,
+ GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
+ GNUNET_CONTAINER_meta_data_destroy (mmeta);
+ if (mdsize == -1)
+ {
+ GNUNET_break (0);
+ GNUNET_free (sb);
+ if (NULL != cont)
+ cont (cont_cls, NULL, _("Internal error."));
+ return NULL;
+ }
+ size = sizeof (struct SBlock) + mdsize + slen + nidlen;
+ sb_enc = GNUNET_malloc (size);
+ GNUNET_CRYPTO_hash (identifier, idlen, &key);
+ GNUNET_CRYPTO_hash (&key, sizeof (GNUNET_HashCode), &id);
+ sks_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
+ sks_uri->type = sks;
+ GNUNET_CRYPTO_rsa_key_get_public (namespace->key, &sb_enc->subspace);
+ GNUNET_CRYPTO_hash (&sb_enc->subspace,
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &sks_uri->data.sks.namespace);
+ sks_uri->data.sks.identifier = GNUNET_strdup (identifier);
+ GNUNET_CRYPTO_hash_xor (&id, &sks_uri->data.sks.namespace,
+ &sb_enc->identifier);
+ GNUNET_CRYPTO_hash_to_aes_key (&key, &sk, &iv);
+ GNUNET_CRYPTO_aes_encrypt (&sb[1], size - sizeof (struct SBlock), &sk, &iv,
+ &sb_enc[1]);
+ sb_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK);
+ sb_enc->purpose.size =
+ htonl (slen + mdsize + nidlen + sizeof (struct SBlock) -
+ sizeof (struct GNUNET_CRYPTO_RsaSignature));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_sign (namespace->key, &sb_enc->purpose,
+ &sb_enc->signature));
+ psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext));
+ psc->uri = sks_uri;
+ psc->cont = cont;
+ psc->namespace = GNUNET_FS_namespace_dup (namespace);
+ psc->cont_cls = cont_cls;
+ if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
+ {
+ GNUNET_free (sb_enc);
+ GNUNET_free (sb);
+ sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
+ return NULL;
+ }
+ psc->dsh = GNUNET_DATASTORE_connect (h->cfg);
+ if (NULL == psc->dsh)
+ {
+ GNUNET_free (sb_enc);
+ GNUNET_free (sb);
+ sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore."));
+ return NULL;
+ }
+ GNUNET_CRYPTO_hash_xor (&sks_uri->data.sks.namespace, &id, &query);
+ if (NULL != update)
+ {
+ psc->nsn = GNUNET_malloc (sizeof (struct NamespaceUpdateNode));
+ psc->nsn->id = GNUNET_strdup (identifier);
+ psc->nsn->update = GNUNET_strdup (update);
+ psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta);
+ psc->nsn->uri = GNUNET_FS_uri_dup (uri);
+ }
+ psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &sb_enc->identifier, size, sb_enc,
+ GNUNET_BLOCK_TYPE_FS_SBLOCK, bo->content_priority,
+ bo->anonymity_level, bo->replication_level,
+ bo->expiration_time, -2, 1,
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc);
+ GNUNET_free (sb);
+ GNUNET_free (sb_enc);
+ return psc;