aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_publish.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-18 19:03:26 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-18 19:03:26 +0000
commitc456c5bb7f9b95d1800ad6e2892a77f40a08493e (patch)
tree8b04e75f8a65225848816d8e588b28413ff9d758 /src/fs/fs_publish.c
parent6d0a62078edfa5c0001acb93d517c674c5124f4e (diff)
downloadgnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.tar.gz
gnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.zip
make all (?) asynchronously operating FS operations actually cancel-able
Diffstat (limited to 'src/fs/fs_publish.c')
-rw-r--r--src/fs/fs_publish.c397
1 files changed, 34 insertions, 363 deletions
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c
index 444128016..134dd21e4 100644
--- a/src/fs/fs_publish.c
+++ b/src/fs/fs_publish.c
@@ -34,13 +34,6 @@
34#include "fs_api.h" 34#include "fs_api.h"
35#include "fs_tree.h" 35#include "fs_tree.h"
36 36
37#define DEBUG_PUBLISH GNUNET_EXTRA_LOGGING
38
39/**
40 * Maximum legal size for a kblock.
41 */
42#define MAX_KBLOCK_SIZE (60 * 1024)
43
44 37
45/** 38/**
46 * Fill in all of the generic fields for 39 * Fill in all of the generic fields for
@@ -78,17 +71,12 @@ GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi,
78/** 71/**
79 * Cleanup the publish context, we're done with it. 72 * Cleanup the publish context, we're done with it.
80 * 73 *
81 * @param cls struct to clean up after 74 * @param pc struct to clean up
82 * @param tc scheduler context
83 */ 75 */
84static void 76static void
85publish_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 77publish_cleanup (struct GNUNET_FS_PublishContext *pc)
86{ 78{
87 struct GNUNET_FS_PublishContext *pc = cls;
88
89#if DEBUG_PUBLISH
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n"); 79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n");
91#endif
92 if (pc->fhc != NULL) 80 if (pc->fhc != NULL)
93 { 81 {
94 GNUNET_CRYPTO_hash_file_cancel (pc->fhc); 82 GNUNET_CRYPTO_hash_file_cancel (pc->fhc);
@@ -136,15 +124,6 @@ ds_put_cont (void *cls, int success,
136 struct GNUNET_FS_ProgressInfo pi; 124 struct GNUNET_FS_ProgressInfo pi;
137 125
138 pc->qre = NULL; 126 pc->qre = NULL;
139 if (GNUNET_SYSERR == pc->in_network_wait)
140 {
141 /* we were aborted in the meantime, finish shutdown! */
142 GNUNET_SCHEDULER_add_continuation (&publish_cleanup, pc,
143 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
144 return;
145 }
146 GNUNET_assert (GNUNET_YES == pc->in_network_wait);
147 pc->in_network_wait = GNUNET_NO;
148 if (GNUNET_SYSERR == success) 127 if (GNUNET_SYSERR == success)
149 { 128 {
150 GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg); 129 GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg);
@@ -238,9 +217,7 @@ finish_release_reserve (void *cls, int success,
238 struct GNUNET_FS_PublishContext *pc = cls; 217 struct GNUNET_FS_PublishContext *pc = cls;
239 218
240 pc->qre = NULL; 219 pc->qre = NULL;
241#if DEBUG_PUBLISH
242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n"); 220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n");
243#endif
244 signal_publish_completion (pc->fi, pc); 221 signal_publish_completion (pc->fi, pc);
245 pc->all_done = GNUNET_YES; 222 pc->all_done = GNUNET_YES;
246 GNUNET_FS_publish_sync_ (pc); 223 GNUNET_FS_publish_sync_ (pc);
@@ -261,6 +238,7 @@ publish_sblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri,
261{ 238{
262 struct GNUNET_FS_PublishContext *pc = cls; 239 struct GNUNET_FS_PublishContext *pc = cls;
263 240
241 pc->sks_pc = NULL;
264 if (NULL != emsg) 242 if (NULL != emsg)
265 { 243 {
266 signal_publish_error (pc->fi, pc, emsg); 244 signal_publish_error (pc->fi, pc, emsg);
@@ -292,9 +270,9 @@ static void
292publish_sblock (struct GNUNET_FS_PublishContext *pc) 270publish_sblock (struct GNUNET_FS_PublishContext *pc)
293{ 271{
294 if (NULL != pc->namespace) 272 if (NULL != pc->namespace)
295 GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid, 273 pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid,
296 pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, 274 pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo,
297 pc->options, &publish_sblocks_cont, pc); 275 pc->options, &publish_sblocks_cont, pc);
298 else 276 else
299 publish_sblocks_cont (pc, NULL, NULL); 277 publish_sblocks_cont (pc, NULL, NULL);
300} 278}
@@ -316,25 +294,22 @@ publish_kblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri,
316 struct GNUNET_FS_PublishContext *pc = cls; 294 struct GNUNET_FS_PublishContext *pc = cls;
317 struct GNUNET_FS_FileInformation *p = pc->fi_pos; 295 struct GNUNET_FS_FileInformation *p = pc->fi_pos;
318 296
297 pc->ksk_pc = NULL;
319 if (NULL != emsg) 298 if (NULL != emsg)
320 { 299 {
321#if DEBUG_PUBLISH
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n", 300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n",
323 emsg); 301 emsg);
324#endif
325 signal_publish_error (p, pc, emsg); 302 signal_publish_error (p, pc, emsg);
326 GNUNET_FS_file_information_sync_ (p); 303 GNUNET_FS_file_information_sync_ (p);
327 GNUNET_FS_publish_sync_ (pc); 304 GNUNET_FS_publish_sync_ (pc);
328 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); 305 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
329 pc->upload_task = 306 pc->upload_task =
330 GNUNET_SCHEDULER_add_with_priority 307 GNUNET_SCHEDULER_add_with_priority
331 (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); 308 (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc);
332 return; 309 return;
333 } 310 }
334#if DEBUG_PUBLISH
335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
336 "KSK blocks published, moving on to next file\n"); 312 "KSK blocks published, moving on to next file\n");
337#endif
338 if (NULL != p->dir) 313 if (NULL != p->dir)
339 signal_publish_completion (p, pc); 314 signal_publish_completion (p, pc);
340 /* move on to next file */ 315 /* move on to next file */
@@ -415,9 +390,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
415 p->te = NULL; 390 p->te = NULL;
416 if (NULL != emsg) 391 if (NULL != emsg)
417 { 392 {
418#if DEBUG_PUBLISH
419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); 393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg);
420#endif
421 GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg); 394 GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg);
422 GNUNET_free (emsg); 395 GNUNET_free (emsg);
423 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; 396 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR;
@@ -425,9 +398,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
425 pi.value.publish.specifics.error.message = p->emsg; 398 pi.value.publish.specifics.error.message = p->emsg;
426 p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); 399 p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0);
427 } 400 }
428#if DEBUG_PUBLISH
429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); 401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n");
430#endif
431 /* final progress event */ 402 /* final progress event */
432 flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); 403 flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri);
433 pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; 404 pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS;
@@ -471,9 +442,7 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
471 p = pc->fi_pos; 442 p = pc->fi_pos;
472 if (NULL == pc->dsh) 443 if (NULL == pc->dsh)
473 { 444 {
474#if DEBUG_PUBLISH
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n"); 445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n");
476#endif
477 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); 446 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task);
478 pc->upload_task = 447 pc->upload_task =
479 GNUNET_SCHEDULER_add_with_priority 448 GNUNET_SCHEDULER_add_with_priority
@@ -481,17 +450,13 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
481 return; 450 return;
482 } 451 }
483 452
484 GNUNET_assert (GNUNET_NO == pc->in_network_wait);
485 pc->in_network_wait = GNUNET_YES;
486 if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) && 453 if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) &&
487 (type == GNUNET_BLOCK_TYPE_FS_DBLOCK)) 454 (type == GNUNET_BLOCK_TYPE_FS_DBLOCK))
488 { 455 {
489#if DEBUG_PUBLISH
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Indexing block `%s' for offset %llu with index size %u\n", 457 "Indexing block `%s' for offset %llu with index size %u\n",
492 GNUNET_h2s (&chk->query), (unsigned long long) offset, 458 GNUNET_h2s (&chk->query), (unsigned long long) offset,
493 sizeof (struct OnDemandBlock)); 459 sizeof (struct OnDemandBlock));
494#endif
495 odb.offset = GNUNET_htonll (offset); 460 odb.offset = GNUNET_htonll (offset);
496 odb.file_id = p->data.file.file_id; 461 odb.file_id = p->data.file.file_id;
497 GNUNET_assert (pc->qre == NULL); 462 GNUNET_assert (pc->qre == NULL);
@@ -505,12 +470,10 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset,
505 &ds_put_cont, pc); 470 &ds_put_cont, pc);
506 return; 471 return;
507 } 472 }
508#if DEBUG_PUBLISH
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 473 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Publishing block `%s' for offset %llu with size %u\n", 474 "Publishing block `%s' for offset %llu with size %u\n",
511 GNUNET_h2s (&chk->query), (unsigned long long) offset, 475 GNUNET_h2s (&chk->query), (unsigned long long) offset,
512 (unsigned int) block_size); 476 (unsigned int) block_size);
513#endif
514 GNUNET_assert (pc->qre == NULL); 477 GNUNET_assert (pc->qre == NULL);
515 pc->qre = 478 pc->qre =
516 GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid, 479 GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid,
@@ -573,9 +536,7 @@ publish_content (struct GNUNET_FS_PublishContext *pc)
573 { 536 {
574 if (p->is_directory) 537 if (p->is_directory)
575 { 538 {
576#if DEBUG_PUBLISH
577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n"); 539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n");
578#endif
579 db = GNUNET_FS_directory_builder_create (p->meta); 540 db = GNUNET_FS_directory_builder_create (p->meta);
580 dirpos = p->data.dir.entries; 541 dirpos = p->data.dir.entries;
581 while (NULL != dirpos) 542 while (NULL != dirpos)
@@ -617,18 +578,14 @@ publish_content (struct GNUNET_FS_PublishContext *pc)
617 GNUNET_FS_file_information_sync_ (p); 578 GNUNET_FS_file_information_sync_ (p);
618 } 579 }
619 size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; 580 size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size;
620#if DEBUG_PUBLISH
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n"); 581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n");
622#endif
623 p->te = 582 p->te =
624 GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader, 583 GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader,
625 &block_proc, &progress_proc, 584 &block_proc, &progress_proc,
626 &encode_cont); 585 &encode_cont);
627 586
628 } 587 }
629#if DEBUG_PUBLISH
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n"); 588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n");
631#endif
632 GNUNET_FS_tree_encoder_next (p->te); 589 GNUNET_FS_tree_encoder_next (p->te);
633} 590}
634 591
@@ -739,10 +696,8 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res)
739 publish_content (pc); 696 publish_content (pc);
740 return; 697 return;
741 } 698 }
742#if DEBUG_PUBLISH
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n", 699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n",
744 p->filename, GNUNET_h2s (res)); 700 p->filename, GNUNET_h2s (res));
745#endif
746 if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) 701 if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
747 { 702 {
748 p->data.file.file_id = *res; 703 p->data.file.file_id = *res;
@@ -779,13 +734,11 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res)
779 ism->device = GNUNET_htonll (dev); 734 ism->device = GNUNET_htonll (dev);
780 ism->inode = GNUNET_htonll (ino); 735 ism->inode = GNUNET_htonll (ino);
781 } 736 }
782#if DEBUG_PUBLISH
783 else 737 else
784 { 738 {
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 _("Failed to get file identifiers for `%s'\n"), p->filename); 740 _("Failed to get file identifiers for `%s'\n"), p->filename);
787 } 741 }
788#endif
789 ism->file_id = *res; 742 ism->file_id = *res;
790 memcpy (&ism[1], fn, slen); 743 memcpy (&ism[1], fn, slen);
791 GNUNET_free (fn); 744 GNUNET_free (fn);
@@ -820,10 +773,8 @@ GNUNET_FS_publish_main_ (void *cls,
820 p = pc->fi_pos; 773 p = pc->fi_pos;
821 if (NULL == p) 774 if (NULL == p)
822 { 775 {
823#if DEBUG_PUBLISH
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Publishing complete, now publishing SKS and KSK blocks.\n"); 777 "Publishing complete, now publishing SKS and KSK blocks.\n");
826#endif
827 /* upload of entire hierarchy complete, 778 /* upload of entire hierarchy complete,
828 * publish namespace entries */ 779 * publish namespace entries */
829 GNUNET_FS_publish_sync_ (pc); 780 GNUNET_FS_publish_sync_ (pc);
@@ -841,9 +792,7 @@ GNUNET_FS_publish_main_ (void *cls,
841 /* abort on error */ 792 /* abort on error */
842 if (NULL != p->emsg) 793 if (NULL != p->emsg)
843 { 794 {
844#if DEBUG_PUBLISH
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg); 795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg);
846#endif
847 /* error with current file, abort all 796 /* error with current file, abort all
848 * related files as well! */ 797 * related files as well! */
849 while (NULL != p->dir) 798 while (NULL != p->dir)
@@ -873,10 +822,8 @@ GNUNET_FS_publish_main_ (void *cls,
873 /* handle completion */ 822 /* handle completion */
874 if (NULL != p->chk_uri) 823 if (NULL != p->chk_uri)
875 { 824 {
876#if DEBUG_PUBLISH
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "File upload complete, now publishing KSK blocks.\n"); 826 "File upload complete, now publishing KSK blocks.\n");
879#endif
880 if (0 == p->bo.anonymity_level) 827 if (0 == p->bo.anonymity_level)
881 { 828 {
882 /* zero anonymity, box CHK URI in LOC URI */ 829 /* zero anonymity, box CHK URI in LOC URI */
@@ -890,8 +837,8 @@ GNUNET_FS_publish_main_ (void *cls,
890 /* upload of "p" complete, publish KBlocks! */ 837 /* upload of "p" complete, publish KBlocks! */
891 if (p->keywords != NULL) 838 if (p->keywords != NULL)
892 { 839 {
893 GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo, 840 pc->ksk_pc = GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo,
894 pc->options, &publish_kblocks_cont, pc); 841 pc->options, &publish_kblocks_cont, pc);
895 } 842 }
896 else 843 else
897 { 844 {
@@ -959,9 +906,7 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi,
959 pc->skip_next_fi_callback = GNUNET_NO; 906 pc->skip_next_fi_callback = GNUNET_NO;
960 return GNUNET_OK; 907 return GNUNET_OK;
961 } 908 }
962#if DEBUG_PUBLISH
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n"); 909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n");
964#endif
965 if (*do_index) 910 if (*do_index)
966 { 911 {
967 /* space for on-demand blocks */ 912 /* space for on-demand blocks */
@@ -1043,9 +988,17 @@ fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi,
1043 pc->skip_next_fi_callback = GNUNET_YES; 988 pc->skip_next_fi_callback = GNUNET_YES;
1044 GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); 989 GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc);
1045 } 990 }
1046#if DEBUG_PUBLISH 991 if (NULL != pc->ksk_pc)
992 {
993 GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
994 pc->ksk_pc = NULL;
995 }
996 if (NULL != pc->sks_pc)
997 {
998 GNUNET_FS_publish_sks_cancel (pc->sks_pc);
999 pc->sks_pc = NULL;
1000 }
1047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n"); 1001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n");
1048#endif
1049 GNUNET_free_non_null (fi->serialization); 1002 GNUNET_free_non_null (fi->serialization);
1050 fi->serialization = NULL; 1003 fi->serialization = NULL;
1051 off = (fi->chk_uri == NULL) ? 0 : length; 1004 off = (fi->chk_uri == NULL) ? 0 : length;
@@ -1086,7 +1039,7 @@ GNUNET_FS_publish_signal_suspend_ (void *cls)
1086 GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); 1039 GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc);
1087 GNUNET_FS_end_top (pc->h, pc->top); 1040 GNUNET_FS_end_top (pc->h, pc->top);
1088 pc->top = NULL; 1041 pc->top = NULL;
1089 publish_cleanup (pc, NULL); 1042 publish_cleanup (pc);
1090} 1043}
1091 1044
1092 1045
@@ -1107,9 +1060,7 @@ finish_reserve (void *cls, int success,
1107 struct GNUNET_FS_PublishContext *pc = cls; 1060 struct GNUNET_FS_PublishContext *pc = cls;
1108 1061
1109 pc->qre = NULL; 1062 pc->qre = NULL;
1110#if DEBUG_PUBLISH
1111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success); 1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success);
1112#endif
1113 if ((msg != NULL) || (success <= 0)) 1064 if ((msg != NULL) || (success <= 0))
1114 { 1065 {
1115 GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"), 1066 GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"),
@@ -1267,14 +1218,17 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc)
1267 struct GNUNET_FS_ProgressInfo pi; 1218 struct GNUNET_FS_ProgressInfo pi;
1268 uint64_t off; 1219 uint64_t off;
1269 1220
1270#if DEBUG_PUBLISH
1271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n"); 1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n");
1272#endif
1273 GNUNET_FS_end_top (pc->h, pc->top); 1222 GNUNET_FS_end_top (pc->h, pc->top);
1274 if (NULL != pc->qre) 1223 if (NULL != pc->ksk_pc)
1275 { 1224 {
1276 GNUNET_DATASTORE_cancel (pc->qre); 1225 GNUNET_FS_publish_ksk_cancel (pc->ksk_pc);
1277 pc->qre = NULL; 1226 pc->ksk_pc = NULL;
1227 }
1228 if (NULL != pc->sks_pc)
1229 {
1230 GNUNET_FS_publish_sks_cancel (pc->sks_pc);
1231 pc->sks_pc = NULL;
1278 } 1232 }
1279 if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) 1233 if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task)
1280 { 1234 {
@@ -1300,299 +1254,16 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc)
1300 GNUNET_free (pc->serialization); 1254 GNUNET_free (pc->serialization);
1301 pc->serialization = NULL; 1255 pc->serialization = NULL;
1302 } 1256 }
1303 if (GNUNET_YES == pc->in_network_wait) 1257 if (NULL != pc->qre)
1304 { 1258 {
1305 pc->in_network_wait = GNUNET_SYSERR; 1259 GNUNET_DATASTORE_cancel (pc->qre);
1306 return; 1260 pc->qre = NULL;
1307 } 1261 }
1308 pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; 1262 pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED;
1309 GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); 1263 GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off));
1310 publish_cleanup (pc, NULL); 1264 publish_cleanup (pc);
1311} 1265}
1312 1266
1313 1267
1314/**
1315 * Context for the KSK publication.
1316 */
1317struct PublishKskContext
1318{
1319
1320 /**
1321 * Keywords to use.
1322 */
1323 struct GNUNET_FS_Uri *ksk_uri;
1324
1325 /**
1326 * Global FS context.
1327 */
1328 struct GNUNET_FS_Handle *h;
1329
1330 /**
1331 * The master block that we are sending
1332 * (in plaintext), has "mdsize+slen" more
1333 * bytes than the struct would suggest.
1334 */
1335 struct KBlock *kb;
1336
1337 /**
1338 * Buffer of the same size as "kb" for
1339 * the encrypted version.
1340 */
1341 struct KBlock *cpy;
1342
1343 /**
1344 * Handle to the datastore, NULL if we are just
1345 * simulating.
1346 */
1347 struct GNUNET_DATASTORE_Handle *dsh;
1348
1349 /**
1350 * Handle to datastore PUT request.
1351 */
1352 struct GNUNET_DATASTORE_QueueEntry *qre;
1353
1354 /**
1355 * Function to call once we're done.
1356 */
1357 GNUNET_FS_PublishContinuation cont;
1358
1359 /**
1360 * Closure for cont.
1361 */
1362 void *cont_cls;
1363
1364 /**
1365 * When should the KBlocks expire?
1366 */
1367 struct GNUNET_FS_BlockOptions bo;
1368
1369 /**
1370 * Size of the serialized metadata.
1371 */
1372 ssize_t mdsize;
1373
1374 /**
1375 * Size of the (CHK) URI as a string.
1376 */
1377 size_t slen;
1378
1379 /**
1380 * Keyword that we are currently processing.
1381 */
1382 unsigned int i;
1383
1384};
1385
1386
1387/**
1388 * Continuation of "GNUNET_FS_publish_ksk" that performs
1389 * the actual publishing operation (iterating over all
1390 * of the keywords).
1391 *
1392 * @param cls closure of type "struct PublishKskContext*"
1393 * @param tc unused
1394 */
1395static void
1396publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1397
1398
1399/**
1400 * Function called by the datastore API with
1401 * the result from the PUT request.
1402 *
1403 * @param cls closure of type "struct PublishKskContext*"
1404 * @param success GNUNET_OK on success
1405 * @param min_expiration minimum expiration time required for content to be stored
1406 * @param msg error message (or NULL)
1407 */
1408static void
1409kb_put_cont (void *cls, int success,
1410 struct GNUNET_TIME_Absolute min_expiration,
1411 const char *msg)
1412{
1413 struct PublishKskContext *pkc = cls;
1414
1415 pkc->qre = NULL;
1416 if (GNUNET_OK != success)
1417 {
1418#if DEBUG_PUBLISH
1419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KB PUT operation complete\n");
1420#endif
1421 if (NULL != pkc->dsh)
1422 {
1423 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1424 pkc->dsh = NULL;
1425 }
1426 GNUNET_free (pkc->cpy);
1427 GNUNET_free (pkc->kb);
1428 pkc->cont (pkc->cont_cls, NULL, msg);
1429 GNUNET_FS_uri_destroy (pkc->ksk_uri);
1430 GNUNET_free (pkc);
1431 return;
1432 }
1433 GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
1434 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1435}
1436
1437
1438/**
1439 * Continuation of "GNUNET_FS_publish_ksk" that performs the actual
1440 * publishing operation (iterating over all of the keywords).
1441 *
1442 * @param cls closure of type "struct PublishKskContext*"
1443 * @param tc unused
1444 */
1445static void
1446publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1447{
1448 struct PublishKskContext *pkc = cls;
1449 const char *keyword;
1450 GNUNET_HashCode key;
1451 GNUNET_HashCode query;
1452 struct GNUNET_CRYPTO_AesSessionKey skey;
1453 struct GNUNET_CRYPTO_AesInitializationVector iv;
1454 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
1455
1456
1457 if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh))
1458 {
1459#if DEBUG_PUBLISH
1460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n");
1461#endif
1462 if (NULL != pkc->dsh)
1463 {
1464 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1465 pkc->dsh = NULL;
1466 }
1467 GNUNET_free (pkc->cpy);
1468 GNUNET_free (pkc->kb);
1469 pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL);
1470 GNUNET_FS_uri_destroy (pkc->ksk_uri);
1471 GNUNET_free (pkc);
1472 return;
1473 }
1474 keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++];
1475#if DEBUG_PUBLISH
1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n",
1477 keyword);
1478#endif
1479 /* first character of keyword indicates if it is
1480 * mandatory or not -- ignore for hashing */
1481 GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key);
1482 GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv);
1483 GNUNET_CRYPTO_aes_encrypt (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv,
1484 &pkc->cpy[1]);
1485 pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key);
1486 GNUNET_assert (NULL != pk);
1487 GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace);
1488 GNUNET_CRYPTO_hash (&pkc->cpy->keyspace,
1489 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1490 &query);
1491 GNUNET_assert (GNUNET_OK ==
1492 GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose,
1493 &pkc->cpy->signature));
1494 GNUNET_CRYPTO_rsa_key_free (pk);
1495 pkc->qre =
1496 GNUNET_DATASTORE_put (pkc->dsh, 0, &query,
1497 pkc->mdsize + sizeof (struct KBlock) + pkc->slen,
1498 pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK,
1499 pkc->bo.content_priority, pkc->bo.anonymity_level,
1500 pkc->bo.replication_level, pkc->bo.expiration_time,
1501 -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
1502 &kb_put_cont, pkc);
1503}
1504
1505
1506/**
1507 * Publish a CHK under various keywords on GNUnet.
1508 *
1509 * @param h handle to the file sharing subsystem
1510 * @param ksk_uri keywords to use
1511 * @param meta metadata to use
1512 * @param uri URI to refer to in the KBlock
1513 * @param bo per-block options
1514 * @param options publication options
1515 * @param cont continuation
1516 * @param cont_cls closure for cont
1517 */
1518void
1519GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
1520 const struct GNUNET_FS_Uri *ksk_uri,
1521 const struct GNUNET_CONTAINER_MetaData *meta,
1522 const struct GNUNET_FS_Uri *uri,
1523 const struct GNUNET_FS_BlockOptions *bo,
1524 enum GNUNET_FS_PublishOptions options,
1525 GNUNET_FS_PublishContinuation cont, void *cont_cls)
1526{
1527 struct PublishKskContext *pkc;
1528 char *uris;
1529 size_t size;
1530 char *kbe;
1531 char *sptr;
1532
1533 GNUNET_assert (NULL != uri);
1534 pkc = GNUNET_malloc (sizeof (struct PublishKskContext));
1535 pkc->h = h;
1536 pkc->bo = *bo;
1537 pkc->cont = cont;
1538 pkc->cont_cls = cont_cls;
1539 if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
1540 {
1541 pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
1542 if (pkc->dsh == NULL)
1543 {
1544 cont (cont_cls, NULL, _("Could not connect to datastore."));
1545 GNUNET_free (pkc);
1546 return;
1547 }
1548 }
1549 if (meta == NULL)
1550 pkc->mdsize = 0;
1551 else
1552 pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
1553 GNUNET_assert (pkc->mdsize >= 0);
1554 uris = GNUNET_FS_uri_to_string (uri);
1555 pkc->slen = strlen (uris) + 1;
1556 size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
1557 if (size > MAX_KBLOCK_SIZE)
1558 {
1559 size = MAX_KBLOCK_SIZE;
1560 pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
1561 }
1562 pkc->kb = GNUNET_malloc (size);
1563 kbe = (char *) &pkc->kb[1];
1564 memcpy (kbe, uris, pkc->slen);
1565 GNUNET_free (uris);
1566 sptr = &kbe[pkc->slen];
1567 if (meta != NULL)
1568 pkc->mdsize =
1569 GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
1570 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
1571 if (pkc->mdsize == -1)
1572 {
1573 GNUNET_break (0);
1574 GNUNET_free (pkc->kb);
1575 if (pkc->dsh != NULL)
1576 {
1577 GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
1578 pkc->dsh = NULL;
1579 }
1580 cont (cont_cls, NULL, _("Internal error."));
1581 GNUNET_free (pkc);
1582 return;
1583 }
1584 size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;
1585
1586 pkc->cpy = GNUNET_malloc (size);
1587 pkc->cpy->purpose.size =
1588 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1589 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
1590 pkc->mdsize + pkc->slen);
1591 pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
1592 pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
1593 GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc,
1594 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1595}
1596
1597 1268
1598/* end of fs_publish.c */ 1269/* end of fs_publish.c */