X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ffs%2Ffs_publish.c;h=6f8a9d2486a13734b6b8eabb832493f199f43b71;hb=6c471eeb15e27f8226492b4860a3c2acb94c5f25;hp=3c5e87edbb50e87aa457725880d122e0224d6a33;hpb=0b7df31372e4eb63732f03f8754607a4dee2b80d;p=oweals%2Fgnunet.git diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 3c5e87edb..6f8a9d248 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -34,13 +34,6 @@ #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 @@ -64,7 +57,7 @@ GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.publish.pctx = (NULL == p->dir) ? NULL : p->dir->client_info; pi->value.publish.filename = p->filename; pi->value.publish.size = - (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; + (p->is_directory == GNUNET_YES) ? p->data.dir.dir_size : p->data.file.file_size; pi->value.publish.eta = GNUNET_TIME_calculate_eta (p->start_time, offset, pi->value.publish.size); pi->value.publish.completed = offset; @@ -78,17 +71,12 @@ GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi, /** * 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); @@ -110,7 +98,7 @@ publish_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } if (pc->client != NULL) { - GNUNET_CLIENT_disconnect (pc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); @@ -136,15 +124,6 @@ ds_put_cont (void *cls, int success, 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); @@ -153,7 +132,7 @@ ds_put_cont (void *cls, int success, pi.value.publish.specifics.error.message = pc->fi_pos->emsg; pc->fi_pos->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi_pos, 0); - if ((pc->fi_pos->is_directory == GNUNET_NO) && + if ((pc->fi_pos->is_directory != GNUNET_YES) && (pc->fi_pos->filename != NULL) && (pc->fi_pos->data.file.do_index == GNUNET_YES)) { @@ -212,7 +191,7 @@ signal_publish_error (struct GNUNET_FS_FileInformation *p, pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.publish.specifics.error.message = emsg; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); - if ((p->is_directory == GNUNET_NO) && (p->filename != NULL) && + if ((p->is_directory != GNUNET_YES) && (p->filename != NULL) && (p->data.file.do_index == GNUNET_YES)) { /* run unindex to clean up */ @@ -238,9 +217,7 @@ finish_release_reserve (void *cls, int success, 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); @@ -261,6 +238,7 @@ publish_sblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, { struct GNUNET_FS_PublishContext *pc = cls; + pc->sks_pc = NULL; if (NULL != emsg) { signal_publish_error (pc->fi, pc, emsg); @@ -292,9 +270,9 @@ static void 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); } @@ -316,25 +294,22 @@ publish_kblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, 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 */ @@ -372,7 +347,7 @@ block_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) const char *dd; p = pc->fi_pos; - if (p->is_directory) + if (p->is_directory == GNUNET_YES) { pt_size = GNUNET_MIN (max, p->data.dir.dir_size - offset); dd = p->data.dir.dir_data; @@ -380,6 +355,8 @@ block_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) } else { + if (UINT64_MAX == offset) + return p->data.file.reader (p->data.file.reader_cls, offset, 0, NULL, NULL); pt_size = GNUNET_MIN (max, p->data.file.file_size - offset); if (pt_size == 0) return 0; /* calling reader with pt_size==0 @@ -410,14 +387,13 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) char *emsg; uint64_t flen; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); p = pc->fi_pos; GNUNET_FS_tree_encoder_finish (p->te, &p->chk_uri, &emsg); 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; @@ -425,18 +401,19 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 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 + else + { /* final progress event */ - flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); - pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; - pi.value.publish.specifics.progress.data = NULL; - pi.value.publish.specifics.progress.offset = flen; - pi.value.publish.specifics.progress.data_len = 0; - pi.value.publish.specifics.progress.depth = GNUNET_FS_compute_depth (flen); - p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, flen); - + GNUNET_assert (NULL != p->chk_uri); + flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); + pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; + pi.value.publish.specifics.progress.data = NULL; + pi.value.publish.specifics.progress.offset = flen; + pi.value.publish.specifics.progress.data_len = 0; + pi.value.publish.specifics.progress.depth = GNUNET_FS_compute_depth (flen); + p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, flen); + } + GNUNET_FS_file_information_sync_ (p); /* continue with main */ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = @@ -471,9 +448,7 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, 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 @@ -481,22 +456,18 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, 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) && + if ((p->is_directory != GNUNET_YES) && (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); pc->qre = - GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid, + GNUNET_DATASTORE_put (pc->dsh, (p->is_directory == GNUNET_YES) ? 0 : pc->rid, &chk->query, sizeof (struct OnDemandBlock), &odb, GNUNET_BLOCK_TYPE_FS_ONDEMAND, p->bo.content_priority, p->bo.anonymity_level, @@ -505,15 +476,13 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, &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, + GNUNET_DATASTORE_put (pc->dsh, (p->is_directory == GNUNET_YES) ? 0 : pc->rid, &chk->query, block_size, block, type, p->bo.content_priority, p->bo.anonymity_level, p->bo.replication_level, p->bo.expiration_time, -2, @@ -571,16 +540,14 @@ publish_content (struct GNUNET_FS_PublishContext *pc) GNUNET_assert (p != NULL); if (NULL == p->te) { - if (p->is_directory) + if (p->is_directory == GNUNET_YES) { -#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) { - if (dirpos->is_directory) + if (dirpos->is_directory == GNUNET_YES) { raw_data = dirpos->data.dir.dir_data; dirpos->data.dir.dir_data = NULL; @@ -602,6 +569,7 @@ publish_content (struct GNUNET_FS_PublishContext *pc) GNUNET_free (raw_data); raw_data = NULL; } + dirpos->data.file.reader (dirpos->data.file.reader_cls, UINT64_MAX, 0, 0, NULL); } } GNUNET_FS_directory_builder_add (db, dirpos->chk_uri, dirpos->meta, @@ -616,19 +584,15 @@ publish_content (struct GNUNET_FS_PublishContext *pc) &p->data.dir.dir_data); GNUNET_FS_file_information_sync_ (p); } - size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; -#if DEBUG_PUBLISH + size = (p->is_directory == GNUNET_YES) ? p->data.dir.dir_size : p->data.file.file_size; 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); } @@ -648,7 +612,7 @@ process_index_start_response (void *cls, const struct GNUNET_MessageHeader *msg) const char *emsg; uint16_t msize; - GNUNET_CLIENT_disconnect (pc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; p = pc->fi_pos; if (msg == NULL) @@ -694,7 +658,7 @@ process_index_start_response (void *cls, const struct GNUNET_MessageHeader *msg) * @param res resulting hash, NULL on error */ static void -hash_for_index_cb (void *cls, const GNUNET_HashCode * res) +hash_for_index_cb (void *cls, const struct GNUNET_HashCode * res) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; @@ -739,10 +703,8 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res) 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; @@ -779,13 +741,11 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * 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); @@ -820,10 +780,8 @@ GNUNET_FS_publish_main_ (void *cls, 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); @@ -831,7 +789,7 @@ GNUNET_FS_publish_main_ (void *cls, return; } /* find starting position */ - while ((p->is_directory) && (NULL != p->data.dir.entries) && (NULL == p->emsg) + while ((p->is_directory == GNUNET_YES) && (NULL != p->data.dir.entries) && (NULL == p->emsg) && (NULL == p->data.dir.entries->chk_uri)) { p = p->data.dir.entries; @@ -841,9 +799,7 @@ GNUNET_FS_publish_main_ (void *cls, /* 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) @@ -873,10 +829,8 @@ GNUNET_FS_publish_main_ (void *cls, /* 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 */ @@ -890,8 +844,8 @@ GNUNET_FS_publish_main_ (void *cls, /* 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 { @@ -899,7 +853,7 @@ GNUNET_FS_publish_main_ (void *cls, } return; } - if ((!p->is_directory) && (p->data.file.do_index)) + if ((p->is_directory != GNUNET_YES) && (p->data.file.do_index)) { if (NULL == p->filename) { @@ -959,9 +913,7 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, 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 */ @@ -996,10 +948,9 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, pi.status = GNUNET_FS_STATUS_PUBLISH_START; *client_info = GNUNET_FS_publish_make_status_ (&pi, pc, fi, 0); GNUNET_FS_file_information_sync_ (fi); - if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta) - && (fi->dir != NULL)) + if ((fi->is_directory) && (fi->dir != NULL)) { - /* process entries in directory */ + /* We are a directory, and we are not top-level; process entries in directory */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_start, pc); } @@ -1008,9 +959,53 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, /** - * Signal the FS's progress function that we are suspending + * Actually signal the FS's progress function that we are suspending * an upload. * + * @param fi the entry in the publish-structure + * @param pc the publish context of which a file is being suspended + */ +static void +suspend_operation (struct GNUNET_FS_FileInformation *fi, + struct GNUNET_FS_PublishContext *pc) +{ + struct GNUNET_FS_ProgressInfo pi; + uint64_t off; + + 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"); + GNUNET_free_non_null (fi->serialization); + fi->serialization = NULL; + off = (fi->chk_uri == NULL) ? 0 : (fi->is_directory == GNUNET_YES) ? fi->data.dir.dir_size : fi->data.file.file_size; + pi.status = GNUNET_FS_STATUS_PUBLISH_SUSPEND; + GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, fi, off)); + if (NULL != pc->qre) + { + GNUNET_DATASTORE_cancel (pc->qre); + pc->qre = NULL; + } + if (NULL != pc->dsh) + { + GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); + pc->dsh = NULL; + } + pc->rid = 0; +} + + +/** + * Signal the FS's progress function that we are suspending + * an upload. Performs the recursion. + * * @param cls closure (of type "struct GNUNET_FS_PublishContext*") * @param fi the entry in the publish-structure * @param length length of the file or directory @@ -1029,8 +1024,6 @@ fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi, void **client_info) { struct GNUNET_FS_PublishContext *pc = cls; - struct GNUNET_FS_ProgressInfo pi; - uint64_t off; if (GNUNET_YES == pc->skip_next_fi_callback) { @@ -1043,26 +1036,8 @@ fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi, pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); } -#if DEBUG_PUBLISH - 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; - pi.status = GNUNET_FS_STATUS_PUBLISH_SUSPEND; - GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, fi, off)); + suspend_operation (fi, pc); *client_info = NULL; - if (NULL != pc->qre) - { - GNUNET_DATASTORE_cancel (pc->qre); - pc->qre = NULL; - } - if (NULL != pc->dsh) - { - GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); - pc->dsh = NULL; - } - pc->rid = 0; return GNUNET_OK; } @@ -1083,10 +1058,12 @@ GNUNET_FS_publish_signal_suspend_ (void *cls) GNUNET_SCHEDULER_cancel (pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_NO_TASK; } + pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); + suspend_operation (pc->fi, pc); GNUNET_FS_end_top (pc->h, pc->top); pc->top = NULL; - publish_cleanup (pc, NULL); + publish_cleanup (pc); } @@ -1107,9 +1084,7 @@ finish_reserve (void *cls, int success, 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"), @@ -1267,19 +1242,17 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) 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->dsh) + if (NULL != pc->sks_pc) { - GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); - pc->dsh = NULL; + GNUNET_FS_publish_sks_cancel (pc->sks_pc); + pc->sks_pc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) { @@ -1297,8 +1270,6 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) pc->fi->serialization = NULL; } off = (pc->fi->chk_uri == NULL) ? 0 : GNUNET_ntohll (pc->fi->chk_uri->data.chk.file_length); - pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; - GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); if (pc->serialization != NULL) { @@ -1307,297 +1278,16 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) GNUNET_free (pc->serialization); pc->serialization = NULL; } - if (GNUNET_YES == pc->in_network_wait) - { - pc->in_network_wait = GNUNET_SYSERR; - return; - } - publish_cleanup (pc, NULL); -} - - -/** - * 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 (NULL != pc->qre) { -#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; + GNUNET_DATASTORE_cancel (pc->qre); + pc->qre = NULL; } - 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); + pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; + GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); + publish_cleanup (pc); } -/** - * 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 */