fs_getopt.c \
fs_list_indexed.c \
fs_publish.c \
+ fs_publish_ksk.c \
fs_misc.c \
fs_namespace.c \
+ fs_namespace_advertise.c \
fs_search.c \
fs_sharetree.c \
fs_tree.c fs_tree.h \
*/
struct GNUNET_DATASTORE_QueueEntry *qre;
+ /**
+ * Context for SKS publishing operation that is part of this publishing operation
+ * (NULL if not active).
+ */
+ struct GNUNET_FS_PublishSksContext *sks_pc;
+
+ /**
+ * Context for KSK publishing operation that is part of this publishing operation
+ * (NULL if not active).
+ */
+ struct GNUNET_FS_PublishKskContext *ksk_pc;
+
/**
* ID of the task performing the upload. NO_TASK if the upload has
* completed.
*/
uint32_t reserve_entries;
- /**
- * Typically GNUNET_NO. Set to GNUNET_YES if "upload_task" is
- * GNUNET_SCHEDULER_NO_TASK and we're waiting for a response from
- * the datastore service (in which case this struct must not be
- * freed until we have that response). If someone tries to stop the
- * download for good during this period, "in_network_wait" is set to
- * GNUNET_SYSERR which will cause the struct to be destroyed right
- * after we have the reply (or timeout) from the datastore service.
- */
- int in_network_wait;
-
/**
* Options for publishing.
*/
/**
* Context for "GNUNET_FS_get_indexed_files".
*/
-struct GetIndexedContext
+struct GNUNET_FS_GetIndexedContext
{
/**
* Handle to global FS context.
* Function called on each response from the FS
* service with information about indexed files.
*
- * @param cls closure (of type "struct GetIndexedContext*")
+ * @param cls closure (of type "struct GNUNET_FS_GetIndexedContext*")
* @param msg message with indexing information
*/
static void
handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
{
- struct GetIndexedContext *gic = cls;
+ struct GNUNET_FS_GetIndexedContext *gic = cls;
const struct IndexInfoMessage *iim;
uint16_t msize;
const char *filename;
_
("Failed to receive response for `%s' request from `%s' service.\n"),
"GET_INDEXED", "fs");
- GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls,
- GNUNET_SCHEDULER_REASON_TIMEOUT);
- GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
- GNUNET_free (gic);
+ (void) gic->iterator (gic->iterator_cls, NULL, NULL);
+ GNUNET_FS_get_indexed_files_cancel (gic);
return;
}
if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END)
{
/* normal end-of-list */
- GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
- GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
- GNUNET_free (gic);
+ (void) gic->iterator (gic->iterator_cls, NULL, NULL);
+ GNUNET_FS_get_indexed_files_cancel (gic);
return;
}
msize = ntohs (msg->size);
_
("Failed to receive valid response for `%s' request from `%s' service.\n"),
"GET_INDEXED", "fs");
- GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls,
- GNUNET_SCHEDULER_REASON_TIMEOUT);
- GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
- GNUNET_free (gic);
+ (void) gic->iterator (gic->iterator_cls, NULL, NULL);
+ GNUNET_FS_get_indexed_files_cancel (gic);
return;
}
if (GNUNET_OK != gic->iterator (gic->iterator_cls, filename, &iim->file_id))
{
- GNUNET_SCHEDULER_add_continuation (gic->cont, gic->cont_cls,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
- GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
- GNUNET_free (gic);
+ GNUNET_FS_get_indexed_files_cancel (gic);
return;
}
/* get more */
* @param h handle to the file sharing subsystem
* @param iterator function to call on each indexed file
* @param iterator_cls closure for iterator
- * @param cont continuation to call when done;
- * reason should be "TIMEOUT" (on
- * error) or "PREREQ_DONE" (on success)
- * @param cont_cls closure for cont
+ * @return NULL on error ('iter' is not called)
*/
-void
+struct GNUNET_FS_GetIndexedContext *
GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
GNUNET_FS_IndexedFileProcessor iterator,
- void *iterator_cls, GNUNET_SCHEDULER_Task cont,
- void *cont_cls)
+ void *iterator_cls)
{
struct GNUNET_CLIENT_Connection *client;
- struct GetIndexedContext *gic;
+ struct GNUNET_FS_GetIndexedContext *gic;
struct GNUNET_MessageHeader msg;
client = GNUNET_CLIENT_connect ("fs", h->cfg);
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Failed to not connect to `%s' service.\n"), "fs");
- GNUNET_SCHEDULER_add_continuation (cont, cont_cls,
- GNUNET_SCHEDULER_REASON_TIMEOUT);
- return;
+ return NULL;
}
-
- gic = GNUNET_malloc (sizeof (struct GetIndexedContext));
+ gic = GNUNET_malloc (sizeof (struct GNUNET_FS_GetIndexedContext));
gic->h = h;
gic->client = client;
gic->iterator = iterator;
gic->iterator_cls = iterator_cls;
- gic->cont = cont;
- gic->cont_cls = cont_cls;
msg.size = htons (sizeof (struct GNUNET_MessageHeader));
msg.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET);
GNUNET_assert (GNUNET_OK ==
GNUNET_YES,
&handle_index_info,
gic));
+ return gic;
+}
+
+
+/**
+ * Cancel iteration over all indexed files.
+ *
+ * @param gic operation to cancel
+ */
+void
+GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic)
+{
+ GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO);
+ GNUNET_free (gic);
}
+
/* end of fs_list_indexed.c */
#include "gnunet_fs_service.h"
#include "fs_api.h"
-#define DEBUG_NAMESPACE GNUNET_EXTRA_LOGGING
-
/**
* Maximum legal size for an sblock.
*/
#define MAX_SBLOCK_SIZE (60 * 1024)
-/**
- * Maximum legal size for an nblock.
- */
-#define MAX_NBLOCK_SIZE (60 * 1024)
-
/**
* Return the name of the directory in which we store
}
-/**
- * Context for advertising a namespace.
- */
-struct AdvertisementContext
-{
- /**
- * Function to call with the result.
- */
- GNUNET_FS_PublishContinuation cont;
-
- /**
- * Closure for cont.
- */
- void *cont_cls;
-
- /**
- * Datastore handle.
- */
- struct GNUNET_DATASTORE_Handle *dsh;
-
- /**
- * Our KSK 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;
-
- /**
- * Block options.
- */
- struct GNUNET_FS_BlockOptions bo;
-
- /**
- * Number of bytes of plaintext.
- */
- size_t pt_size;
-
- /**
- * 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.
- *
- * @param cls closure (our struct AdvertismentContext)
- * @param success GNUNET_SYSERR on failure
- * @param min_expiration minimum expiration time required for content to be stored
- * @param msg NULL on success, otherwise an error message
- */
-static void
-advertisement_cont (void *cls, int success,
- struct GNUNET_TIME_Absolute min_expiration,
- 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)
- {
- /* error! */
- GNUNET_SCHEDULER_add_continuation (&do_disconnect, ac->dsh,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
- if (msg == NULL)
- {
- GNUNET_break (0);
- msg = _("Unknown error");
- }
- if (ac->cont != NULL)
- 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 (&do_disconnect, ac->dsh,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
- if (ac->cont != NULL)
- 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_FS_NBLOCK, ac->bo.content_priority,
- ac->bo.anonymity_level, ac->bo.replication_level,
- ac->bo.expiration_time, -2, 1,
- GNUNET_CONSTANTS_SERVICE_TIMEOUT, &advertisement_cont,
- ac);
-}
-
-
-/**
- * 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 bo block options
- * @param rootEntry name of the root of the namespace
- * @param cont continuation
- * @param cont_cls closure for cont
- */
-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,
- const struct GNUNET_FS_BlockOptions *bo,
- const char *rootEntry,
- GNUNET_FS_PublishContinuation cont,
- void *cont_cls)
-{
- size_t reslen;
- size_t size;
- ssize_t mdsize;
- struct NBlock *nb;
- char *mdst;
- struct GNUNET_DATASTORE_Handle *dsh;
- struct AdvertisementContext *ctx;
- char *pt;
-
- /* create advertisements */
- mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
- if (-1 == mdsize)
- {
- cont (cont_cls, NULL, _("Failed to serialize meta data"));
- return;
- }
- reslen = strlen (rootEntry) + 1;
- size = mdsize + sizeof (struct NBlock) + reslen;
- if (size > MAX_NBLOCK_SIZE)
- {
- size = MAX_NBLOCK_SIZE;
- mdsize = size - sizeof (struct NBlock) - reslen;
- }
-
- pt = GNUNET_malloc (mdsize + reslen);
- memcpy (pt, rootEntry, reslen);
- mdst = &pt[reslen];
- mdsize =
- GNUNET_CONTAINER_meta_data_serialize (meta, &mdst, mdsize,
- GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
- if (mdsize == -1)
- {
- GNUNET_break (0);
- GNUNET_free (pt);
- cont (cont_cls, NULL, _("Failed to serialize meta data"));
- return;
- }
- 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);
- 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->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->bo = *bo;
- advertisement_cont (ctx, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
-}
/**
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink",
namespace->filename);
}
- if (0 == namespace->rc)
+ if (0 != namespace->rc)
+ return GNUNET_OK;
+ GNUNET_CRYPTO_rsa_key_free (namespace->key);
+ GNUNET_free (namespace->filename);
+ GNUNET_free (namespace->name);
+ for (i = 0; i < namespace->update_node_count; i++)
{
- GNUNET_CRYPTO_rsa_key_free (namespace->key);
- GNUNET_free (namespace->filename);
- GNUNET_free (namespace->name);
- for (i = 0; i < namespace->update_node_count; i++)
- {
- nsn = namespace->update_nodes[i];
- GNUNET_CONTAINER_meta_data_destroy (nsn->md);
- GNUNET_FS_uri_destroy (nsn->uri);
- GNUNET_free (nsn->id);
- GNUNET_free (nsn->update);
- GNUNET_free (nsn);
- }
- GNUNET_array_grow (namespace->update_nodes, namespace->update_node_count,
- 0);
- if (namespace->update_map != NULL)
- GNUNET_CONTAINER_multihashmap_destroy (namespace->update_map);
- GNUNET_free (namespace);
- }
+ nsn = namespace->update_nodes[i];
+ GNUNET_CONTAINER_meta_data_destroy (nsn->md);
+ GNUNET_FS_uri_destroy (nsn->uri);
+ GNUNET_free (nsn->id);
+ GNUNET_free (nsn->update);
+ GNUNET_free (nsn);
+ }
+ GNUNET_array_grow (namespace->update_nodes, namespace->update_node_count,
+ 0);
+ if (namespace->update_map != NULL)
+ GNUNET_CONTAINER_multihashmap_destroy (namespace->update_map);
+ GNUNET_free (namespace);
return GNUNET_OK;
}
}
-
-
/**
* Context for the SKS publication.
*/
-struct PublishSksContext
+struct GNUNET_FS_PublishSksContext
{
/**
*/
void *cont_cls;
+ /**
+ * Handle for our datastore request.
+ */
+ struct GNUNET_DATASTORE_QueueEntry *dqe;
};
* Function called by the datastore API with
* the result from the PUT (SBlock) request.
*
- * @param cls closure of type "struct PublishSksContext*"
+ * @param cls closure of type "struct GNUNET_FS_PublishSksContext*"
* @param success GNUNET_OK on success
* @param min_expiration minimum expiration time required for content to be stored
* @param msg error message (or NULL)
struct GNUNET_TIME_Absolute min_expiration,
const char *msg)
{
- struct PublishSksContext *psc = cls;
+ struct GNUNET_FS_PublishSksContext *psc = cls;
GNUNET_HashCode hc;
- if (NULL != psc->dsh)
- {
- GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO);
- psc->dsh = NULL;
- }
+ psc->dqe = NULL;
if (GNUNET_OK != success)
{
- if (psc->cont != NULL)
+ if (NULL != psc->cont)
psc->cont (psc->cont_cls, NULL, msg);
+ GNUNET_FS_publish_sks_cancel (psc);
+ return;
}
- else
+ if (NULL != psc->nsn)
{
- if (psc->nsn != NULL)
+ /* FIXME: this can be done much more
+ * efficiently by simply appending to the
+ * file and overwriting the 4-byte header */
+ if (psc->namespace->update_nodes == NULL)
+ read_update_information_graph (psc->namespace);
+ GNUNET_array_append (psc->namespace->update_nodes,
+ psc->namespace->update_node_count, psc->nsn);
+ if (psc->namespace->update_map != NULL)
{
- /* FIXME: this can be done much more
- * efficiently by simply appending to the
- * file and overwriting the 4-byte header */
- if (psc->namespace->update_nodes == NULL)
- read_update_information_graph (psc->namespace);
- GNUNET_array_append (psc->namespace->update_nodes,
- psc->namespace->update_node_count, psc->nsn);
- if (psc->namespace->update_map != NULL)
- {
- GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc);
- GNUNET_CONTAINER_multihashmap_put (psc->namespace->update_map, &hc,
- psc->nsn,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- }
- psc->nsn = NULL;
- write_update_information_graph (psc->namespace);
+ GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc);
+ GNUNET_CONTAINER_multihashmap_put (psc->namespace->update_map, &hc,
+ psc->nsn,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
}
- if (psc->cont != NULL)
- psc->cont (psc->cont_cls, psc->uri, NULL);
- }
- GNUNET_FS_namespace_delete (psc->namespace, GNUNET_NO);
- GNUNET_FS_uri_destroy (psc->uri);
- if (psc->nsn != NULL)
- {
- GNUNET_CONTAINER_meta_data_destroy (psc->nsn->md);
- GNUNET_FS_uri_destroy (psc->nsn->uri);
- GNUNET_free (psc->nsn->id);
- GNUNET_free (psc->nsn->update);
- GNUNET_free (psc->nsn);
+ psc->nsn = NULL;
+ write_update_information_graph (psc->namespace);
}
- GNUNET_free (psc);
+ if (NULL != psc->cont)
+ psc->cont (psc->cont_cls, psc->uri, NULL);
+ GNUNET_FS_publish_sks_cancel (psc);
}
* @param options publication options
* @param cont continuation
* @param cont_cls closure for cont
+ * @return NULL on error ('cont' will still be called)
*/
-void
+struct GNUNET_FS_PublishSksContext *
GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
struct GNUNET_FS_Namespace *namespace,
const char *identifier, const char *update,
enum GNUNET_FS_PublishOptions options,
GNUNET_FS_PublishContinuation cont, void *cont_cls)
{
- struct PublishSksContext *psc;
+ struct GNUNET_FS_PublishSksContext *psc;
struct GNUNET_CRYPTO_AesSessionKey sk;
struct GNUNET_CRYPTO_AesInitializationVector iv;
struct GNUNET_FS_Uri *sks_uri;
{
GNUNET_break (0);
GNUNET_free (sb);
- cont (cont_cls, NULL, _("Internal error."));
- return;
+ if (NULL != cont)
+ cont (cont_cls, NULL, _("Internal error."));
+ return NULL;
}
size = sizeof (struct SBlock) + mdsize + slen + nidlen;
sb_enc = GNUNET_malloc (size);
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_rsa_sign (namespace->key, &sb_enc->purpose,
&sb_enc->signature));
- psc = GNUNET_malloc (sizeof (struct PublishSksContext));
+ psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext));
psc->uri = sks_uri;
psc->cont = cont;
- psc->namespace = namespace;
- namespace->rc++;
+ 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;
+ 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;
+ return NULL;
}
GNUNET_CRYPTO_hash_xor (&sks_uri->data.sks.namespace, &id, &query);
if (NULL != update)
psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta);
psc->nsn->uri = GNUNET_FS_uri_dup (uri);
}
- 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);
+ 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;
+}
+
+
+/**
+ * Abort the SKS publishing operation.
+ *
+ * @param sc context of the operation to abort.
+ */
+void
+GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc)
+{
+ if (NULL != psc->dqe)
+ {
+ GNUNET_DATASTORE_cancel (psc->dqe);
+ psc->dqe = NULL;
+ }
+ if (NULL != psc->dsh)
+ {
+ GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO);
+ psc->dsh = NULL;
+ }
+ GNUNET_FS_namespace_delete (psc->namespace, GNUNET_NO);
+ GNUNET_FS_uri_destroy (psc->uri);
+ if (NULL != psc->nsn)
+ {
+ GNUNET_CONTAINER_meta_data_destroy (psc->nsn->md);
+ GNUNET_FS_uri_destroy (psc->nsn->uri);
+ GNUNET_free (psc->nsn->id);
+ GNUNET_free (psc->nsn->update);
+ GNUNET_free (psc->nsn);
+ }
+ GNUNET_free (psc);
}
read_update_information_graph (namespace);
if (namespace->update_nodes == NULL)
{
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"No updateable nodes found for ID `%s'\n", next_id);
-#endif
return; /* no nodes */
}
if (namespace->update_map == NULL)
&process_update_node, &pc);
return;
}
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Calculating TREEs to find roots of update trees\n");
-#endif
/* Find heads of TREEs in update graph */
nug = ++namespace->nug_gen;
fc.tree_array = NULL;
nsn = namespace->update_nodes[i];
if (nsn->nug == nug)
{
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id,
nsn->nug);
-#endif
continue; /* already placed in TREE */
}
GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc);
GNUNET_array_append (fc.tree_array, fc.tree_array_size, nsn);
nsn->tree_id = fc.id;
}
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting new TREE %u with node `%s'\n", nsn->tree_id,
nsn->id);
-#endif
/* put all nodes with same identifier into this TREE */
GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc);
fc.id = nsn->tree_id;
fc.tree_array[fc.id] = nsn;
nsn->tree_id = fc.id;
}
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id,
fc.id);
-#endif
}
for (i = 0; i < fc.tree_array_size; i++)
{
nsn = fc.tree_array[i];
if (NULL != nsn)
{
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Root of TREE %u is node `%s'\n", i,
nsn->id);
-#endif
-
ip (ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update);
}
}
GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0);
-#if DEBUG_NAMESPACE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n");
-#endif
}
--- /dev/null
+/*
+ This file is part of GNUnet
+ (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
+
+ 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 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.
+
+ 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.
+*/
+
+/**
+ * @file fs/fs_namespace_advertise.c
+ * @brief advertise namespaces (creating NBlocks)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_signatures.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_fs_service.h"
+#include "fs_api.h"
+
+
+/**
+ * Maximum legal size for an nblock.
+ */
+#define MAX_NBLOCK_SIZE (60 * 1024)
+
+
+/**
+ * Context for advertising a namespace.
+ */
+struct GNUNET_FS_AdvertisementContext
+{
+ /**
+ * Function to call with the result.
+ */
+ GNUNET_FS_PublishContinuation cont;
+
+ /**
+ * Closure for cont.
+ */
+ void *cont_cls;
+
+ /**
+ * Datastore handle.
+ */
+ struct GNUNET_DATASTORE_Handle *dsh;
+
+ /**
+ * Our KSK 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;
+
+ /**
+ * Current datastore queue entry for advertising.
+ */
+ struct GNUNET_DATASTORE_QueueEntry *dqe;
+
+ /**
+ * Block options.
+ */
+ struct GNUNET_FS_BlockOptions bo;
+
+ /**
+ * Number of bytes of plaintext.
+ */
+ size_t pt_size;
+
+ /**
+ * Current keyword offset.
+ */
+ unsigned int pos;
+};
+
+
+// FIXME: I see no good reason why this should need to be done
+// in a new task (anymore). Integrate with 'cancel' function below?
+/**
+ * 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.
+ *
+ * @param cls closure (our struct GNUNET_FS_AdvertismentContext)
+ * @param success GNUNET_SYSERR on failure
+ * @param min_expiration minimum expiration time required for content to be stored
+ * @param msg NULL on success, otherwise an error message
+ */
+static void
+advertisement_cont (void *cls, int success,
+ struct GNUNET_TIME_Absolute min_expiration,
+ const char *msg)
+{
+ struct GNUNET_FS_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;
+
+ ac->dqe = NULL;
+ if (GNUNET_SYSERR == success)
+ {
+ /* error! */
+ (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh);
+ ac->dsh = NULL;
+ if (msg == NULL)
+ {
+ GNUNET_break (0);
+ msg = _("Unknown error");
+ }
+ if (ac->cont != NULL)
+ {
+ ac->cont (ac->cont_cls, NULL, msg);
+ ac->cont = NULL;
+ }
+ GNUNET_FS_namespace_advertise_cancel (ac);
+ return;
+ }
+ if (ac->pos == ac->ksk_uri->data.ksk.keywordCount)
+ {
+ /* done! */
+ (void) GNUNET_SCHEDULER_add_now (&do_disconnect, ac->dsh);
+ ac->dsh = NULL;
+ if (ac->cont != NULL)
+ {
+ ac->cont (ac->cont_cls, ac->ksk_uri, NULL);
+ ac->cont = NULL;
+ }
+ GNUNET_FS_namespace_advertise_cancel (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);
+ ac->dqe = GNUNET_DATASTORE_put (ac->dsh, 0 /* no reservation */ ,
+ &query, ac->pt_size + sizeof (struct NBlock), ac->nb,
+ GNUNET_BLOCK_TYPE_FS_NBLOCK, ac->bo.content_priority,
+ ac->bo.anonymity_level, ac->bo.replication_level,
+ ac->bo.expiration_time, -2, 1,
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT, &advertisement_cont,
+ ac);
+}
+
+
+/**
+ * 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 bo block options
+ * @param rootEntry name of the root of the namespace
+ * @param cont continuation
+ * @param cont_cls closure for cont
+ * @return NULL on error ('cont' is still called)
+ */
+struct GNUNET_FS_AdvertisementContext *
+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,
+ const struct GNUNET_FS_BlockOptions *bo,
+ const char *rootEntry,
+ GNUNET_FS_PublishContinuation cont,
+ void *cont_cls)
+{
+ size_t reslen;
+ size_t size;
+ ssize_t mdsize;
+ struct NBlock *nb;
+ char *mdst;
+ struct GNUNET_DATASTORE_Handle *dsh;
+ struct GNUNET_FS_AdvertisementContext *ctx;
+ char *pt;
+
+ /* create advertisements */
+ mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
+ if (-1 == mdsize)
+ {
+ cont (cont_cls, NULL, _("Failed to serialize meta data"));
+ return NULL;
+ }
+ reslen = strlen (rootEntry) + 1;
+ size = mdsize + sizeof (struct NBlock) + reslen;
+ if (size > MAX_NBLOCK_SIZE)
+ {
+ size = MAX_NBLOCK_SIZE;
+ mdsize = size - sizeof (struct NBlock) - reslen;
+ }
+
+ pt = GNUNET_malloc (mdsize + reslen);
+ memcpy (pt, rootEntry, reslen);
+ mdst = &pt[reslen];
+ mdsize =
+ GNUNET_CONTAINER_meta_data_serialize (meta, &mdst, mdsize,
+ GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
+ if (-1 == mdsize)
+ {
+ GNUNET_break (0);
+ GNUNET_free (pt);
+ cont (cont_cls, NULL, _("Failed to serialize meta data"));
+ return NULL;
+ }
+ 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);
+ if (NULL == dsh)
+ {
+ GNUNET_free (nb);
+ GNUNET_free (pt);
+ cont (cont_cls, NULL, _("Failed to connect to datastore service"));
+ return NULL;
+ }
+ ctx = GNUNET_malloc (sizeof (struct GNUNET_FS_AdvertisementContext));
+ ctx->cont = cont;
+ ctx->cont_cls = cont_cls;
+ ctx->dsh = dsh;
+ 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->bo = *bo;
+ advertisement_cont (ctx, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
+ return ctx;
+}
+
+
+/**
+ * Abort the namespace advertisement operation.
+ *
+ * @param pkc context of the operation to abort.
+ */
+void
+GNUNET_FS_namespace_advertise_cancel (struct GNUNET_FS_AdvertisementContext *ac)
+{
+ if (NULL != ac->dqe)
+ {
+ GNUNET_DATASTORE_cancel (ac->dqe);
+ ac->dqe = NULL;
+ }
+ if (NULL != ac->dsh)
+ {
+ GNUNET_DATASTORE_disconnect (ac->dsh, GNUNET_NO);
+ ac->dsh = 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);
+}
+
+
+/* end of fs_namespace_advertise.c */
#include "fs_api.h"
#include "fs_tree.h"
-#define DEBUG_PUBLISH GNUNET_EXTRA_LOGGING
-
-/**
- * Maximum legal size for a kblock.
- */
-#define MAX_KBLOCK_SIZE (60 * 1024)
-
/**
* Fill in all of the generic fields for
/**
* Cleanup the publish context, we're done with it.
*
- * @param cls struct to clean up after
- * @param tc scheduler context
+ * @param pc struct to clean up
*/
static void
-publish_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+publish_cleanup (struct GNUNET_FS_PublishContext *pc)
{
- struct GNUNET_FS_PublishContext *pc = cls;
-
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n");
-#endif
if (pc->fhc != NULL)
{
GNUNET_CRYPTO_hash_file_cancel (pc->fhc);
struct GNUNET_FS_ProgressInfo pi;
pc->qre = NULL;
- if (GNUNET_SYSERR == pc->in_network_wait)
- {
- /* we were aborted in the meantime, finish shutdown! */
- GNUNET_SCHEDULER_add_continuation (&publish_cleanup, pc,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
- return;
- }
- GNUNET_assert (GNUNET_YES == pc->in_network_wait);
- pc->in_network_wait = GNUNET_NO;
if (GNUNET_SYSERR == success)
{
GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg);
struct GNUNET_FS_PublishContext *pc = cls;
pc->qre = NULL;
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n");
-#endif
signal_publish_completion (pc->fi, pc);
pc->all_done = GNUNET_YES;
GNUNET_FS_publish_sync_ (pc);
{
struct GNUNET_FS_PublishContext *pc = cls;
+ pc->sks_pc = NULL;
if (NULL != emsg)
{
signal_publish_error (pc->fi, pc, emsg);
publish_sblock (struct GNUNET_FS_PublishContext *pc)
{
if (NULL != pc->namespace)
- GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid,
- pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo,
- pc->options, &publish_sblocks_cont, pc);
+ pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid,
+ pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo,
+ pc->options, &publish_sblocks_cont, pc);
else
publish_sblocks_cont (pc, NULL, NULL);
}
struct GNUNET_FS_PublishContext *pc = cls;
struct GNUNET_FS_FileInformation *p = pc->fi_pos;
+ pc->ksk_pc = NULL;
if (NULL != emsg)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n",
emsg);
-#endif
signal_publish_error (p, pc, emsg);
GNUNET_FS_file_information_sync_ (p);
GNUNET_FS_publish_sync_ (pc);
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
pc->upload_task =
- GNUNET_SCHEDULER_add_with_priority
- (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc);
+ GNUNET_SCHEDULER_add_with_priority
+ (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc);
return;
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"KSK blocks published, moving on to next file\n");
-#endif
if (NULL != p->dir)
signal_publish_completion (p, pc);
/* move on to next file */
p->te = NULL;
if (NULL != emsg)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg);
-#endif
GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg);
GNUNET_free (emsg);
pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR;
pi.value.publish.specifics.error.message = p->emsg;
p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0);
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n");
-#endif
/* final progress event */
flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri);
pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS;
p = pc->fi_pos;
if (NULL == pc->dsh)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n");
-#endif
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
pc->upload_task =
GNUNET_SCHEDULER_add_with_priority
return;
}
- GNUNET_assert (GNUNET_NO == pc->in_network_wait);
- pc->in_network_wait = GNUNET_YES;
if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) &&
(type == GNUNET_BLOCK_TYPE_FS_DBLOCK))
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Indexing block `%s' for offset %llu with index size %u\n",
GNUNET_h2s (&chk->query), (unsigned long long) offset,
sizeof (struct OnDemandBlock));
-#endif
odb.offset = GNUNET_htonll (offset);
odb.file_id = p->data.file.file_id;
GNUNET_assert (pc->qre == NULL);
&ds_put_cont, pc);
return;
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Publishing block `%s' for offset %llu with size %u\n",
GNUNET_h2s (&chk->query), (unsigned long long) offset,
(unsigned int) block_size);
-#endif
GNUNET_assert (pc->qre == NULL);
pc->qre =
GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid,
{
if (p->is_directory)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n");
-#endif
db = GNUNET_FS_directory_builder_create (p->meta);
dirpos = p->data.dir.entries;
while (NULL != dirpos)
GNUNET_FS_file_information_sync_ (p);
}
size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size;
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n");
-#endif
p->te =
GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader,
&block_proc, &progress_proc,
&encode_cont);
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n");
-#endif
GNUNET_FS_tree_encoder_next (p->te);
}
publish_content (pc);
return;
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n",
p->filename, GNUNET_h2s (res));
-#endif
if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
{
p->data.file.file_id = *res;
ism->device = GNUNET_htonll (dev);
ism->inode = GNUNET_htonll (ino);
}
-#if DEBUG_PUBLISH
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
_("Failed to get file identifiers for `%s'\n"), p->filename);
}
-#endif
ism->file_id = *res;
memcpy (&ism[1], fn, slen);
GNUNET_free (fn);
p = pc->fi_pos;
if (NULL == p)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Publishing complete, now publishing SKS and KSK blocks.\n");
-#endif
/* upload of entire hierarchy complete,
* publish namespace entries */
GNUNET_FS_publish_sync_ (pc);
/* abort on error */
if (NULL != p->emsg)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg);
-#endif
/* error with current file, abort all
* related files as well! */
while (NULL != p->dir)
/* handle completion */
if (NULL != p->chk_uri)
{
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"File upload complete, now publishing KSK blocks.\n");
-#endif
if (0 == p->bo.anonymity_level)
{
/* zero anonymity, box CHK URI in LOC URI */
/* upload of "p" complete, publish KBlocks! */
if (p->keywords != NULL)
{
- GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo,
- pc->options, &publish_kblocks_cont, pc);
+ pc->ksk_pc = GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo,
+ pc->options, &publish_kblocks_cont, pc);
}
else
{
pc->skip_next_fi_callback = GNUNET_NO;
return GNUNET_OK;
}
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n");
-#endif
if (*do_index)
{
/* space for on-demand blocks */
pc->skip_next_fi_callback = GNUNET_YES;
GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc);
}
-#if DEBUG_PUBLISH
+ if (NULL != pc->ksk_pc)
+ {
+ GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
+ pc->ksk_pc = NULL;
+ }
+ if (NULL != pc->sks_pc)
+ {
+ GNUNET_FS_publish_sks_cancel (pc->sks_pc);
+ pc->sks_pc = NULL;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n");
-#endif
GNUNET_free_non_null (fi->serialization);
fi->serialization = NULL;
off = (fi->chk_uri == NULL) ? 0 : length;
GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc);
GNUNET_FS_end_top (pc->h, pc->top);
pc->top = NULL;
- publish_cleanup (pc, NULL);
+ publish_cleanup (pc);
}
struct GNUNET_FS_PublishContext *pc = cls;
pc->qre = NULL;
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success);
-#endif
if ((msg != NULL) || (success <= 0))
{
GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"),
struct GNUNET_FS_ProgressInfo pi;
uint64_t off;
-#if DEBUG_PUBLISH
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n");
-#endif
GNUNET_FS_end_top (pc->h, pc->top);
- if (NULL != pc->qre)
+ if (NULL != pc->ksk_pc)
{
- GNUNET_DATASTORE_cancel (pc->qre);
- pc->qre = NULL;
+ GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
+ pc->ksk_pc = NULL;
+ }
+ if (NULL != pc->sks_pc)
+ {
+ GNUNET_FS_publish_sks_cancel (pc->sks_pc);
+ pc->sks_pc = NULL;
}
if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task)
{
GNUNET_free (pc->serialization);
pc->serialization = NULL;
}
- if (GNUNET_YES == pc->in_network_wait)
+ if (NULL != pc->qre)
{
- pc->in_network_wait = GNUNET_SYSERR;
- return;
+ GNUNET_DATASTORE_cancel (pc->qre);
+ pc->qre = NULL;
}
pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED;
GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off));
- publish_cleanup (pc, NULL);
+ publish_cleanup (pc);
}
-/**
- * Context for the KSK publication.
- */
-struct PublishKskContext
-{
-
- /**
- * Keywords to use.
- */
- struct GNUNET_FS_Uri *ksk_uri;
-
- /**
- * Global FS context.
- */
- struct GNUNET_FS_Handle *h;
-
- /**
- * The master block that we are sending
- * (in plaintext), has "mdsize+slen" more
- * bytes than the struct would suggest.
- */
- struct KBlock *kb;
-
- /**
- * Buffer of the same size as "kb" for
- * the encrypted version.
- */
- struct KBlock *cpy;
-
- /**
- * Handle to the datastore, NULL if we are just
- * simulating.
- */
- struct GNUNET_DATASTORE_Handle *dsh;
-
- /**
- * Handle to datastore PUT request.
- */
- struct GNUNET_DATASTORE_QueueEntry *qre;
-
- /**
- * Function to call once we're done.
- */
- GNUNET_FS_PublishContinuation cont;
-
- /**
- * Closure for cont.
- */
- void *cont_cls;
-
- /**
- * When should the KBlocks expire?
- */
- struct GNUNET_FS_BlockOptions bo;
-
- /**
- * Size of the serialized metadata.
- */
- ssize_t mdsize;
-
- /**
- * Size of the (CHK) URI as a string.
- */
- size_t slen;
-
- /**
- * Keyword that we are currently processing.
- */
- unsigned int i;
-
-};
-
-
-/**
- * Continuation of "GNUNET_FS_publish_ksk" that performs
- * the actual publishing operation (iterating over all
- * of the keywords).
- *
- * @param cls closure of type "struct PublishKskContext*"
- * @param tc unused
- */
-static void
-publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Function called by the datastore API with
- * the result from the PUT request.
- *
- * @param cls closure of type "struct PublishKskContext*"
- * @param success GNUNET_OK on success
- * @param min_expiration minimum expiration time required for content to be stored
- * @param msg error message (or NULL)
- */
-static void
-kb_put_cont (void *cls, int success,
- struct GNUNET_TIME_Absolute min_expiration,
- const char *msg)
-{
- struct PublishKskContext *pkc = cls;
-
- pkc->qre = NULL;
- if (GNUNET_OK != success)
- {
-#if DEBUG_PUBLISH
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KB PUT operation complete\n");
-#endif
- if (NULL != pkc->dsh)
- {
- GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
- pkc->dsh = NULL;
- }
- GNUNET_free (pkc->cpy);
- GNUNET_free (pkc->kb);
- pkc->cont (pkc->cont_cls, NULL, msg);
- GNUNET_FS_uri_destroy (pkc->ksk_uri);
- GNUNET_free (pkc);
- return;
- }
- GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-}
-
-
-/**
- * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
- * publishing operation (iterating over all of the keywords).
- *
- * @param cls closure of type "struct PublishKskContext*"
- * @param tc unused
- */
-static void
-publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct PublishKskContext *pkc = 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 ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
- {
-#if DEBUG_PUBLISH
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
-#endif
- if (NULL != pkc->dsh)
- {
- GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
- pkc->dsh = NULL;
- }
- GNUNET_free (pkc->cpy);
- GNUNET_free (pkc->kb);
- pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
- GNUNET_FS_uri_destroy (pkc->ksk_uri);
- GNUNET_free (pkc);
- return;
- }
- keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
-#if DEBUG_PUBLISH
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
- keyword);
-#endif
- /* 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 (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv,
- &pkc->cpy[1]);
- pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
- GNUNET_assert (NULL != pk);
- GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace);
- GNUNET_CRYPTO_hash (&pkc->cpy->keyspace,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &query);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose,
- &pkc->cpy->signature));
- GNUNET_CRYPTO_rsa_key_free (pk);
- pkc->qre =
- GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
- pkc->mdsize + sizeof (struct KBlock) + pkc->slen,
- pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK,
- pkc->bo.content_priority, pkc->bo.anonymity_level,
- pkc->bo.replication_level, pkc->bo.expiration_time,
- -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- &kb_put_cont, pkc);
-}
-
-
-/**
- * Publish a CHK under various keywords on GNUnet.
- *
- * @param h handle to the file sharing subsystem
- * @param ksk_uri keywords to use
- * @param meta metadata to use
- * @param uri URI to refer to in the KBlock
- * @param bo per-block options
- * @param options publication options
- * @param cont continuation
- * @param cont_cls closure for cont
- */
-void
-GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
- const struct GNUNET_FS_Uri *ksk_uri,
- const struct GNUNET_CONTAINER_MetaData *meta,
- const struct GNUNET_FS_Uri *uri,
- const struct GNUNET_FS_BlockOptions *bo,
- enum GNUNET_FS_PublishOptions options,
- GNUNET_FS_PublishContinuation cont, void *cont_cls)
-{
- struct PublishKskContext *pkc;
- char *uris;
- size_t size;
- char *kbe;
- char *sptr;
-
- GNUNET_assert (NULL != uri);
- pkc = GNUNET_malloc (sizeof (struct PublishKskContext));
- pkc->h = h;
- pkc->bo = *bo;
- pkc->cont = cont;
- pkc->cont_cls = cont_cls;
- if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
- {
- pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
- if (pkc->dsh == NULL)
- {
- cont (cont_cls, NULL, _("Could not connect to datastore."));
- GNUNET_free (pkc);
- return;
- }
- }
- if (meta == NULL)
- pkc->mdsize = 0;
- else
- pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
- GNUNET_assert (pkc->mdsize >= 0);
- uris = GNUNET_FS_uri_to_string (uri);
- pkc->slen = strlen (uris) + 1;
- size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
- if (size > MAX_KBLOCK_SIZE)
- {
- size = MAX_KBLOCK_SIZE;
- pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
- }
- pkc->kb = GNUNET_malloc (size);
- kbe = (char *) &pkc->kb[1];
- memcpy (kbe, uris, pkc->slen);
- GNUNET_free (uris);
- sptr = &kbe[pkc->slen];
- if (meta != NULL)
- pkc->mdsize =
- GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
- GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
- if (pkc->mdsize == -1)
- {
- GNUNET_break (0);
- GNUNET_free (pkc->kb);
- if (pkc->dsh != NULL)
- {
- GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
- pkc->dsh = NULL;
- }
- cont (cont_cls, NULL, _("Internal error."));
- GNUNET_free (pkc);
- return;
- }
- size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;
-
- pkc->cpy = GNUNET_malloc (size);
- pkc->cpy->purpose.size =
- htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
- pkc->mdsize + pkc->slen);
- pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
- pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
- GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-}
-
/* end of fs_publish.c */
--- /dev/null
+/*
+ This file is part of GNUnet.
+ (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors)
+
+ 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 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.
+
+ 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.
+*/
+
+/**
+ * @file fs/fs_publish_ksk.c
+ * @brief publish a URI under a keyword in GNUnet
+ * @see https://gnunet.org/encoding
+ * @author Krista Bennett
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_signatures.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_fs_service.h"
+#include "fs_api.h"
+#include "fs_tree.h"
+
+
+/**
+ * Maximum legal size for a kblock.
+ */
+#define MAX_KBLOCK_SIZE (60 * 1024)
+
+
+/**
+ * Context for the KSK publication.
+ */
+struct GNUNET_FS_PublishKskContext
+{
+
+ /**
+ * Keywords to use.
+ */
+ struct GNUNET_FS_Uri *ksk_uri;
+
+ /**
+ * Global FS context.
+ */
+ struct GNUNET_FS_Handle *h;
+
+ /**
+ * The master block that we are sending
+ * (in plaintext), has "mdsize+slen" more
+ * bytes than the struct would suggest.
+ */
+ struct KBlock *kb;
+
+ /**
+ * Buffer of the same size as "kb" for
+ * the encrypted version.
+ */
+ struct KBlock *cpy;
+
+ /**
+ * Handle to the datastore, NULL if we are just
+ * simulating.
+ */
+ struct GNUNET_DATASTORE_Handle *dsh;
+
+ /**
+ * Handle to datastore PUT request.
+ */
+ struct GNUNET_DATASTORE_QueueEntry *qre;
+
+ /**
+ * Current task.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier ksk_task;
+
+ /**
+ * Function to call once we're done.
+ */
+ GNUNET_FS_PublishContinuation cont;
+
+ /**
+ * Closure for cont.
+ */
+ void *cont_cls;
+
+ /**
+ * When should the KBlocks expire?
+ */
+ struct GNUNET_FS_BlockOptions bo;
+
+ /**
+ * Size of the serialized metadata.
+ */
+ ssize_t mdsize;
+
+ /**
+ * Size of the (CHK) URI as a string.
+ */
+ size_t slen;
+
+ /**
+ * Keyword that we are currently processing.
+ */
+ unsigned int i;
+
+};
+
+
+/**
+ * Continuation of "GNUNET_FS_publish_ksk" that performs
+ * the actual publishing operation (iterating over all
+ * of the keywords).
+ *
+ * @param cls closure of type "struct PublishKskContext*"
+ * @param tc unused
+ */
+static void
+publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Function called by the datastore API with
+ * the result from the PUT request.
+ *
+ * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
+ * @param success GNUNET_OK on success
+ * @param min_expiration minimum expiration time required for content to be stored
+ * @param msg error message (or NULL)
+ */
+static void
+kb_put_cont (void *cls, int success,
+ struct GNUNET_TIME_Absolute min_expiration,
+ const char *msg)
+{
+ struct GNUNET_FS_PublishKskContext *pkc = cls;
+
+ pkc->qre = NULL;
+ if (GNUNET_OK != success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "KBlock PUT operation failed: %s\n", msg);
+ pkc->cont (pkc->cont_cls, NULL, msg);
+ GNUNET_FS_publish_ksk_cancel (pkc);
+ return;
+ }
+ pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
+}
+
+
+/**
+ * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
+ * publishing operation (iterating over all of the keywords).
+ *
+ * @param cls closure of type "struct GNUNET_FS_PublishKskContext*"
+ * @param tc unused
+ */
+static void
+publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_FS_PublishKskContext *pkc = 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;
+
+ pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
+ if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
+ pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
+ GNUNET_FS_publish_ksk_cancel (pkc);
+ return;
+ }
+ keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
+ keyword);
+ /* 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 (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv,
+ &pkc->cpy[1]);
+ pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
+ GNUNET_assert (NULL != pk);
+ GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace);
+ GNUNET_CRYPTO_hash (&pkc->cpy->keyspace,
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &query);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose,
+ &pkc->cpy->signature));
+ GNUNET_CRYPTO_rsa_key_free (pk);
+ pkc->qre =
+ GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
+ pkc->mdsize + sizeof (struct KBlock) + pkc->slen,
+ pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK,
+ pkc->bo.content_priority, pkc->bo.anonymity_level,
+ pkc->bo.replication_level, pkc->bo.expiration_time,
+ -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ &kb_put_cont, pkc);
+}
+
+
+/**
+ * Publish a CHK under various keywords on GNUnet.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param ksk_uri keywords to use
+ * @param meta metadata to use
+ * @param uri URI to refer to in the KBlock
+ * @param bo per-block options
+ * @param options publication options
+ * @param cont continuation
+ * @param cont_cls closure for cont
+ * @return NULL on error ('cont' will still be called)
+ */
+struct GNUNET_FS_PublishKskContext *
+GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
+ const struct GNUNET_FS_Uri *ksk_uri,
+ const struct GNUNET_CONTAINER_MetaData *meta,
+ const struct GNUNET_FS_Uri *uri,
+ const struct GNUNET_FS_BlockOptions *bo,
+ enum GNUNET_FS_PublishOptions options,
+ GNUNET_FS_PublishContinuation cont, void *cont_cls)
+{
+ struct GNUNET_FS_PublishKskContext *pkc;
+ char *uris;
+ size_t size;
+ char *kbe;
+ char *sptr;
+
+ GNUNET_assert (NULL != uri);
+ pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext));
+ pkc->h = h;
+ pkc->bo = *bo;
+ pkc->cont = cont;
+ pkc->cont_cls = cont_cls;
+ if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
+ {
+ pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
+ if (NULL == pkc->dsh)
+ {
+ cont (cont_cls, NULL, _("Could not connect to datastore."));
+ GNUNET_free (pkc);
+ return NULL;
+ }
+ }
+ if (meta == NULL)
+ pkc->mdsize = 0;
+ else
+ pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
+ GNUNET_assert (pkc->mdsize >= 0);
+ uris = GNUNET_FS_uri_to_string (uri);
+ pkc->slen = strlen (uris) + 1;
+ size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
+ if (size > MAX_KBLOCK_SIZE)
+ {
+ size = MAX_KBLOCK_SIZE;
+ pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
+ }
+ pkc->kb = GNUNET_malloc (size);
+ kbe = (char *) &pkc->kb[1];
+ memcpy (kbe, uris, pkc->slen);
+ GNUNET_free (uris);
+ sptr = &kbe[pkc->slen];
+ if (meta != NULL)
+ pkc->mdsize =
+ GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
+ GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
+ if (-1 == pkc->mdsize)
+ {
+ GNUNET_break (0);
+ GNUNET_free (pkc->kb);
+ if (pkc->dsh != NULL)
+ {
+ GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
+ pkc->dsh = NULL;
+ }
+ GNUNET_free (pkc);
+ cont (cont_cls, NULL, _("Internal error."));
+ return NULL;
+ }
+ size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;
+
+ pkc->cpy = GNUNET_malloc (size);
+ pkc->cpy->purpose.size =
+ htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
+ pkc->mdsize + pkc->slen);
+ pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
+ pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
+ pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
+ return pkc;
+}
+
+
+/**
+ * Abort the KSK publishing operation.
+ *
+ * @param pkc context of the operation to abort.
+ */
+void
+GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != pkc->ksk_task)
+ {
+ GNUNET_SCHEDULER_cancel (pkc->ksk_task);
+ pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != pkc->qre)
+ {
+ GNUNET_DATASTORE_cancel (pkc->qre);
+ pkc->qre = NULL;
+ }
+ if (NULL != pkc->dsh)
+ {
+ GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
+ pkc->dsh = NULL;
+ }
+ GNUNET_free (pkc->cpy);
+ GNUNET_free (pkc->kb);
+ GNUNET_FS_uri_destroy (pkc->ksk_uri);
+ GNUNET_free (pkc);
+}
+
+
+/* end of fs_publish_ksk.c */
if (pt_size !=
te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg))
{
- GNUNET_SCHEDULER_add_continuation (te->cont, te->cls,
- GNUNET_SCHEDULER_REASON_TIMEOUT);
+ te->cont (te->cls, NULL);
te->in_next = GNUNET_NO;
return;
}
static int verbose;
-/**
- * Shutdown this process.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_FS_stop (fs);
- fs = NULL;
-}
-
-
/**
* Print indexed filenames to stdout.
*
static int
print_indexed (void *cls, const char *filename, const GNUNET_HashCode * file_id)
{
+ if (NULL == filename)
+ {
+ GNUNET_FS_stop (fs);
+ fs = NULL;
+ return GNUNET_OK;
+ }
if (verbose)
FPRINTF (stdout, "%s: %s\n", GNUNET_h2s (file_id), filename);
else
ret = 1;
return;
}
- GNUNET_FS_get_indexed_files (fs, &print_indexed, NULL, &do_shutdown, NULL);
+ if (NULL == GNUNET_FS_get_indexed_files (fs, &print_indexed, NULL))
+ {
+ ret = 2;
+ GNUNET_FS_stop (fs);
+ fs = NULL;
+ return;
+ }
}
}
{
GNUNET_FS_publish_sks (ctx, ns, this_id, next_id, meta, uri, &bo,
GNUNET_FS_PUBLISH_OPTION_NONE,
- uri_sks_continuation, NULL);
+ &uri_sks_continuation, NULL);
GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_NO));
return;
}
const char *emsg);
+/**
+ * Handle to cancel publish KSK operation.
+ */
+struct GNUNET_FS_PublishKskContext;
+
+
/**
* Publish a KBlock on GNUnet.
*
* @param options publication options
* @param cont continuation
* @param cont_cls closure for cont
+ * @return NULL on error ('cont' will still be called)
*/
-void
+struct GNUNET_FS_PublishKskContext *
GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
const struct GNUNET_FS_Uri *ksk_uri,
const struct GNUNET_CONTAINER_MetaData *meta,
GNUNET_FS_PublishContinuation cont, void *cont_cls);
+/**
+ * Abort the KSK publishing operation.
+ *
+ * @param pkc context of the operation to abort.
+ */
+void
+GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc);
+
+
+/**
+ * Handle to cancel publish SKS operation.
+ */
+struct GNUNET_FS_PublishSksContext;
+
+
/**
* Publish an SBlock on GNUnet.
*
* @param options publication options
* @param cont continuation
* @param cont_cls closure for cont
+ * @return NULL on error ('cont' will still be called)
*/
-void
+struct GNUNET_FS_PublishSksContext *
GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h,
struct GNUNET_FS_Namespace *namespace,
const char *identifier, const char *update,
GNUNET_FS_PublishContinuation cont, void *cont_cls);
+/**
+ * Abort the SKS publishing operation.
+ *
+ * @param psc context of the operation to abort.
+ */
+void
+GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc);
+
+
/**
* Type of a function called by "GNUNET_FS_get_indexed_files".
*
* @param cls closure
- * @param filename the name of the file
+ * @param filename the name of the file, NULL for end of list
* @param file_id hash of the contents of the indexed file
* @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
*/
const GNUNET_HashCode * file_id);
+/**
+ * Handle to cancel 'GNUNET_FS_get_indexed_files'.
+ */
+struct GNUNET_FS_GetIndexedContext;
+
+
/**
* Iterate over all indexed files.
*
* @param h handle to the file sharing subsystem
* @param iterator function to call on each indexed file
* @param iterator_cls closure for iterator
- * @param cont continuation to call when done;
- * reason should be "TIMEOUT" (on
- * error) or "PREREQ_DONE" (on success)
- * @param cont_cls closure for cont
+ * @return NULL on error ('iter' is not called)
*/
-void
+struct GNUNET_FS_GetIndexedContext *
GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
GNUNET_FS_IndexedFileProcessor iterator,
- void *iterator_cls, GNUNET_SCHEDULER_Task cont,
- void *cont_cls);
+ void *iterator_cls);
+
+
+/**
+ * Cancel iteration over all indexed files.
+ *
+ * @param gic operation to cancel
+ */
+void
+GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic);
/**
GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc);
+/**
+ * Context for advertising a namespace.
+ */
+struct GNUNET_FS_AdvertisementContext;
+
+
/**
* Publish an advertismement for a namespace.
*
* @param rootEntry name of the root of the namespace
* @param cont continuation
* @param cont_cls closure for cont
+ * @return NULL on error ('cont' will still be called)
*/
-void
+struct GNUNET_FS_AdvertisementContext *
GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
struct GNUNET_FS_Uri *ksk_uri,
struct GNUNET_FS_Namespace *namespace,
void *cont_cls);
+/**
+ * Abort the namespace advertisement operation.
+ *
+ * @param pkc context of the operation to abort.
+ */
+void
+GNUNET_FS_namespace_advertise_cancel (struct GNUNET_FS_AdvertisementContext *ac);
+
+
/**
* Create a namespace with the given name; if one already
* exists, return a handle to the existing namespace.