diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-08-30 13:46:28 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-08-30 13:46:28 +0000 |
commit | 5cf21b88fb81906c3da589495da11291d5c12d35 (patch) | |
tree | f573ce1a0d67926753ff2f3a24e15ee621bc3eb1 /src | |
parent | cabc8ba699f76cab751b97014d9375ec74612448 (diff) | |
download | gnunet-5cf21b88fb81906c3da589495da11291d5c12d35.tar.gz gnunet-5cf21b88fb81906c3da589495da11291d5c12d35.zip |
kblocks
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/fs.h | 34 | ||||
-rw-r--r-- | src/fs/fs_publish.c | 662 | ||||
-rw-r--r-- | src/fs/gnunet-publish.c | 7 |
3 files changed, 586 insertions, 117 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index 66190a42d..f0d9718a2 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -445,6 +445,11 @@ struct GNUNET_FS_PublishContext | |||
445 | int in_network_wait; | 445 | int in_network_wait; |
446 | 446 | ||
447 | /** | 447 | /** |
448 | * Options for publishing. | ||
449 | */ | ||
450 | enum GNUNET_FS_PublishOptions options; | ||
451 | |||
452 | /** | ||
448 | * Current position in the file-tree for the | 453 | * Current position in the file-tree for the |
449 | * upload. | 454 | * upload. |
450 | */ | 455 | */ |
@@ -495,4 +500,33 @@ struct GNUNET_FS_Namespace | |||
495 | }; | 500 | }; |
496 | 501 | ||
497 | 502 | ||
503 | /** | ||
504 | * @brief keyword block (advertising data under a keyword) | ||
505 | */ | ||
506 | struct GNUNET_FS_KBlock | ||
507 | { | ||
508 | |||
509 | /** | ||
510 | * GNUNET_RSA_Signature using RSA-key generated from search keyword. | ||
511 | */ | ||
512 | struct GNUNET_CRYPTO_RsaSignature signature; | ||
513 | |||
514 | /** | ||
515 | * What is being signed and why? | ||
516 | */ | ||
517 | struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; | ||
518 | |||
519 | /** | ||
520 | * Key generated (!) from the H(keyword) as the seed! | ||
521 | */ | ||
522 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded keyspace; | ||
523 | |||
524 | /* 0-terminated URI here */ | ||
525 | |||
526 | /* variable-size Meta-Data follows here */ | ||
527 | |||
528 | }; | ||
529 | |||
498 | #endif | 530 | #endif |
531 | |||
532 | /* end of fs.h */ | ||
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 124f73743..b9bf1dc9c 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c | |||
@@ -26,7 +26,6 @@ | |||
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
27 | * | 27 | * |
28 | * TODO: | 28 | * TODO: |
29 | * - KBlocks | ||
30 | * - SBlocks | 29 | * - SBlocks |
31 | * - indexing support | 30 | * - indexing support |
32 | * - code-sharing with unindex (can wait) | 31 | * - code-sharing with unindex (can wait) |
@@ -36,12 +35,15 @@ | |||
36 | 35 | ||
37 | #include "platform.h" | 36 | #include "platform.h" |
38 | #include "gnunet_constants.h" | 37 | #include "gnunet_constants.h" |
38 | #include "gnunet_signatures.h" | ||
39 | #include "gnunet_util_lib.h" | 39 | #include "gnunet_util_lib.h" |
40 | #include "gnunet_fs_service.h" | 40 | #include "gnunet_fs_service.h" |
41 | #include "fs.h" | 41 | #include "fs.h" |
42 | 42 | ||
43 | #define DEBUG_PUBLISH GNUNET_YES | 43 | #define DEBUG_PUBLISH GNUNET_YES |
44 | 44 | ||
45 | #define MAX_KBLOCK_SIZE 60000 | ||
46 | |||
45 | /** | 47 | /** |
46 | * Main function that performs the upload. | 48 | * Main function that performs the upload. |
47 | * @param cls "struct GNUNET_FS_PublishContext" identifies the upload | 49 | * @param cls "struct GNUNET_FS_PublishContext" identifies the upload |
@@ -58,8 +60,7 @@ do_upload (void *cls, | |||
58 | struct PutContCtx | 60 | struct PutContCtx |
59 | { | 61 | { |
60 | /** | 62 | /** |
61 | * Publishing context for which the datastore | 63 | * Current publishing context. |
62 | * PUT request was executed. | ||
63 | */ | 64 | */ |
64 | struct GNUNET_FS_PublishContext *sc; | 65 | struct GNUNET_FS_PublishContext *sc; |
65 | 66 | ||
@@ -72,6 +73,11 @@ struct PutContCtx | |||
72 | * Function to run next, if any (can be NULL). | 73 | * Function to run next, if any (can be NULL). |
73 | */ | 74 | */ |
74 | GNUNET_SCHEDULER_Task cont; | 75 | GNUNET_SCHEDULER_Task cont; |
76 | |||
77 | /** | ||
78 | * Closure for cont. | ||
79 | */ | ||
80 | void *cont_cls; | ||
75 | }; | 81 | }; |
76 | 82 | ||
77 | 83 | ||
@@ -173,56 +179,12 @@ ds_put_cont (void *cls, | |||
173 | GNUNET_SCHEDULER_NO_TASK, | 179 | GNUNET_SCHEDULER_NO_TASK, |
174 | GNUNET_TIME_UNIT_ZERO, | 180 | GNUNET_TIME_UNIT_ZERO, |
175 | pcc->cont, | 181 | pcc->cont, |
176 | pcc->sc); | 182 | pcc->cont_cls); |
177 | GNUNET_free (pcc); | 183 | GNUNET_free (pcc); |
178 | } | 184 | } |
179 | 185 | ||
180 | 186 | ||
181 | /** | 187 | /** |
182 | * We need to publish a specific block. Do it. Then continue with | ||
183 | * the main task. | ||
184 | * | ||
185 | * @param sc overall upload data | ||
186 | * @param p file that the block belongs to (needed for options!) | ||
187 | * @param query what the block should be indexed under | ||
188 | * @param blk encoded block to publish | ||
189 | * @param blk_size size of the block | ||
190 | * @param blk_type type of the block | ||
191 | * @param cont function to run when done | ||
192 | */ | ||
193 | static void | ||
194 | publish_block (struct GNUNET_FS_PublishContext *sc, | ||
195 | struct GNUNET_FS_FileInformation *p, | ||
196 | const GNUNET_HashCode *query, | ||
197 | const void* blk, | ||
198 | uint16_t blk_size, | ||
199 | uint32_t blk_type, | ||
200 | GNUNET_SCHEDULER_Task cont) | ||
201 | { | ||
202 | struct PutContCtx * dpc_cls; | ||
203 | |||
204 | dpc_cls = GNUNET_malloc(sizeof(struct PutContCtx)); | ||
205 | dpc_cls->cont = cont; | ||
206 | dpc_cls->sc = sc; | ||
207 | dpc_cls->p = p; | ||
208 | GNUNET_assert (GNUNET_NO == sc->in_network_wait); | ||
209 | sc->in_network_wait = GNUNET_YES; | ||
210 | GNUNET_DATASTORE_put (sc->dsh, | ||
211 | sc->rid, | ||
212 | query, | ||
213 | blk_size, | ||
214 | blk, | ||
215 | blk_type, | ||
216 | p->priority, | ||
217 | p->anonymity, | ||
218 | p->expirationTime, | ||
219 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
220 | &ds_put_cont, | ||
221 | dpc_cls); | ||
222 | } | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Generate the callback that signals clients | 188 | * Generate the callback that signals clients |
227 | * that a file (or directory) has been completely | 189 | * that a file (or directory) has been completely |
228 | * published. | 190 | * published. |
@@ -247,6 +209,59 @@ signal_publish_completion (struct GNUNET_FS_FileInformation *p, | |||
247 | 209 | ||
248 | 210 | ||
249 | /** | 211 | /** |
212 | * Generate the callback that signals clients | ||
213 | * that a file (or directory) has encountered | ||
214 | * a problem during publication. | ||
215 | * | ||
216 | * @param p the upload that had trouble | ||
217 | * @param sc context of the publication | ||
218 | * @param emsg error message | ||
219 | */ | ||
220 | static void | ||
221 | signal_publish_error (struct GNUNET_FS_FileInformation *p, | ||
222 | struct GNUNET_FS_PublishContext *sc, | ||
223 | const char *emsg) | ||
224 | { | ||
225 | struct GNUNET_FS_ProgressInfo pi; | ||
226 | |||
227 | p->emsg = GNUNET_strdup (emsg); | ||
228 | pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; | ||
229 | make_publish_status (&pi, sc, p); | ||
230 | pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; | ||
231 | pi.value.publish.specifics.error.message =emsg; | ||
232 | p->client_info | ||
233 | = sc->h->upcb (sc->h->upcb_cls, | ||
234 | &pi); | ||
235 | } | ||
236 | |||
237 | |||
238 | /** | ||
239 | * We've finished publishing the SBlock as part of a larger upload. | ||
240 | * Check the result and complete the larger upload. | ||
241 | * | ||
242 | * @param cls the "struct GNUNET_FS_PublishContext*" of the larger upload | ||
243 | * @param uri URI of the published SBlock | ||
244 | * @param emsg NULL on success, otherwise error message | ||
245 | */ | ||
246 | static void | ||
247 | publish_sblocks_cont (void *cls, | ||
248 | const struct GNUNET_FS_Uri *uri, | ||
249 | const char *emsg) | ||
250 | { | ||
251 | struct GNUNET_FS_PublishContext *sc = cls; | ||
252 | if (NULL != emsg) | ||
253 | { | ||
254 | signal_publish_error (sc->fi, | ||
255 | sc, | ||
256 | emsg); | ||
257 | return; | ||
258 | } | ||
259 | // FIXME: release the datastore reserve here! | ||
260 | signal_publish_completion (sc->fi, sc); | ||
261 | } | ||
262 | |||
263 | |||
264 | /** | ||
250 | * We are almost done publishing the structure, | 265 | * We are almost done publishing the structure, |
251 | * add SBlocks (if needed). | 266 | * add SBlocks (if needed). |
252 | * | 267 | * |
@@ -255,52 +270,63 @@ signal_publish_completion (struct GNUNET_FS_FileInformation *p, | |||
255 | static void | 270 | static void |
256 | publish_sblock (struct GNUNET_FS_PublishContext *sc) | 271 | publish_sblock (struct GNUNET_FS_PublishContext *sc) |
257 | { | 272 | { |
258 | struct GNUNET_FS_FileInformation *p; | ||
259 | p = sc->fi; | ||
260 | |||
261 | if (NULL != sc->namespace) | 273 | if (NULL != sc->namespace) |
262 | GNUNET_FS_publish_sks (sc->h, | 274 | GNUNET_FS_publish_sks (sc->h, |
263 | sc->namespace, | 275 | sc->namespace, |
264 | sc->nid, | 276 | sc->nid, |
265 | sc->nuid, | 277 | sc->nuid, |
266 | p->meta, | 278 | sc->fi->meta, |
267 | p->chk_uri, | 279 | sc->fi->chk_uri, |
268 | p->expirationTime, | 280 | sc->fi->expirationTime, |
269 | p->anonymity, | 281 | sc->fi->anonymity, |
270 | p->priority); | 282 | sc->fi->priority, |
271 | // FIXME: release the datastore reserve here! | 283 | sc->options, |
272 | signal_publish_completion (p, sc); | 284 | &publish_sblocks_cont, |
285 | sc); | ||
286 | else | ||
287 | publish_sblocks_cont (sc, NULL, NULL); | ||
273 | } | 288 | } |
274 | 289 | ||
275 | 290 | ||
276 | /** | 291 | /** |
277 | * We have uploaded a file or directory; now publish | 292 | * We've finished publishing a KBlock |
278 | * the KBlocks in the global keyword space so that | 293 | * as part of a larger upload. Check |
279 | * it can be found. Then continue with the | 294 | * the result and continue the larger |
280 | * main task. | 295 | * upload. |
281 | * | 296 | * |
282 | * @param sc overall upload data | 297 | * @param cls the "struct GNUNET_FS_PublishContext*" of the larger upload |
283 | * @param p specific file or directory for which kblocks | 298 | * @param uri URI of the published blocks |
284 | * should be created | 299 | * @param emsg NULL on success, otherwise error message |
285 | */ | 300 | */ |
286 | static void | 301 | static void |
287 | publish_kblocks (struct GNUNET_FS_PublishContext *sc, | 302 | publish_kblocks_cont (void *cls, |
288 | struct GNUNET_FS_FileInformation *p) | 303 | const struct GNUNET_FS_Uri *uri, |
304 | const char *emsg) | ||
289 | { | 305 | { |
290 | unsigned int i; | 306 | struct GNUNET_FS_PublishContext *sc = cls; |
307 | struct GNUNET_FS_FileInformation *p = sc->fi_pos; | ||
291 | 308 | ||
292 | // FIXME: use cps here instead... | 309 | if (NULL != emsg) |
293 | for (i=0;i<p->keywords->data.ksk.keywordCount;i++) | 310 | { |
294 | GNUNET_FS_publish_ksk (sc->h, | 311 | signal_publish_error (p, sc, emsg); |
295 | p->keywords->data.ksk.keywords[i], | 312 | sc->upload_task |
296 | p->meta, | 313 | = GNUNET_SCHEDULER_add_delayed (sc->h->sched, |
297 | p->chk_uri, | 314 | GNUNET_NO, |
298 | p->expirationTime, | 315 | GNUNET_SCHEDULER_PRIORITY_BACKGROUND, |
299 | p->anonymity, | 316 | GNUNET_SCHEDULER_NO_TASK, |
300 | p->priority); | 317 | GNUNET_TIME_UNIT_ZERO, |
318 | &do_upload, | ||
319 | sc); | ||
320 | return; | ||
321 | } | ||
301 | GNUNET_FS_file_information_sync (p); | 322 | GNUNET_FS_file_information_sync (p); |
302 | if (NULL != p->dir) | 323 | if (NULL != p->dir) |
303 | signal_publish_completion (p, sc); | 324 | signal_publish_completion (p, sc); |
325 | /* move on to next file */ | ||
326 | if (NULL != p->next) | ||
327 | sc->fi_pos = p->next; | ||
328 | else | ||
329 | sc->fi_pos = p->dir; | ||
304 | sc->upload_task | 330 | sc->upload_task |
305 | = GNUNET_SCHEDULER_add_delayed (sc->h->sched, | 331 | = GNUNET_SCHEDULER_add_delayed (sc->h->sched, |
306 | GNUNET_NO, | 332 | GNUNET_NO, |
@@ -435,6 +461,7 @@ publish_content (struct GNUNET_FS_PublishContext *sc, | |||
435 | struct GNUNET_FS_FileInformation *dirpos; | 461 | struct GNUNET_FS_FileInformation *dirpos; |
436 | void *raw_data; | 462 | void *raw_data; |
437 | char *dd; | 463 | char *dd; |
464 | struct PutContCtx * dpc_cls; | ||
438 | 465 | ||
439 | // FIXME: figure out how to share this code | 466 | // FIXME: figure out how to share this code |
440 | // with unindex! | 467 | // with unindex! |
@@ -473,7 +500,7 @@ publish_content (struct GNUNET_FS_PublishContext *sc, | |||
473 | } | 500 | } |
474 | } | 501 | } |
475 | } | 502 | } |
476 | GNUNET_FS_directory_builder_add (db, | 503 | GNUNET_FS_directory_builder_add (db, |
477 | dirpos->chk_uri, | 504 | dirpos->chk_uri, |
478 | dirpos->meta, | 505 | dirpos->meta, |
479 | raw_data); | 506 | raw_data); |
@@ -555,18 +582,44 @@ publish_content (struct GNUNET_FS_PublishContext *sc, | |||
555 | &sk, | 582 | &sk, |
556 | &iv, | 583 | &iv, |
557 | enc); | 584 | enc); |
558 | // NOTE: this call (and progress below) is all that really differs | 585 | // NOTE: this block below is all that really differs |
559 | // between publish/unindex! Parameterize & move this code! | 586 | // between publish/unindex! Parameterize & move this code! |
560 | // FIXME: something around here would need to change | 587 | // FIXME: something around here would need to change |
561 | // for indexing! | 588 | // for indexing! |
562 | publish_block (sc, p, | 589 | if (NULL == sc->dsh) |
563 | &mychk->query, | 590 | { |
564 | enc, | 591 | sc->upload_task |
565 | pt_size, | 592 | = GNUNET_SCHEDULER_add_delayed (sc->h->sched, |
566 | (p->current_depth == p->chk_tree_depth) | 593 | GNUNET_NO, |
567 | ? GNUNET_DATASTORE_BLOCKTYPE_DBLOCK | 594 | GNUNET_SCHEDULER_PRIORITY_BACKGROUND, |
568 | : GNUNET_DATASTORE_BLOCKTYPE_IBLOCK, | 595 | GNUNET_SCHEDULER_NO_TASK, |
569 | &do_upload); | 596 | GNUNET_TIME_UNIT_ZERO, |
597 | &do_upload, | ||
598 | sc); | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | GNUNET_assert (GNUNET_NO == sc->in_network_wait); | ||
603 | sc->in_network_wait = GNUNET_YES; | ||
604 | dpc_cls = GNUNET_malloc(sizeof(struct PutContCtx)); | ||
605 | dpc_cls->cont = &do_upload; | ||
606 | dpc_cls->cont_cls = sc; | ||
607 | dpc_cls->p = p; | ||
608 | GNUNET_DATASTORE_put (sc->dsh, | ||
609 | sc->rid, | ||
610 | &mychk->query, | ||
611 | pt_size, | ||
612 | enc, | ||
613 | (p->current_depth == p->chk_tree_depth) | ||
614 | ? GNUNET_DATASTORE_BLOCKTYPE_DBLOCK | ||
615 | : GNUNET_DATASTORE_BLOCKTYPE_IBLOCK, | ||
616 | p->priority, | ||
617 | p->anonymity, | ||
618 | p->expirationTime, | ||
619 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
620 | &ds_put_cont, | ||
621 | dpc_cls); | ||
622 | } | ||
570 | if (p->current_depth == p->chk_tree_depth) | 623 | if (p->current_depth == p->chk_tree_depth) |
571 | { | 624 | { |
572 | pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; | 625 | pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; |
@@ -629,6 +682,16 @@ do_upload (void *cls, | |||
629 | publish_sblock (sc); | 682 | publish_sblock (sc); |
630 | return; | 683 | return; |
631 | } | 684 | } |
685 | /* find starting position */ | ||
686 | while ( (p->is_directory) && | ||
687 | (NULL != p->data.dir.entries) && | ||
688 | (NULL == p->emsg) && | ||
689 | (NULL == p->data.dir.entries->chk_uri) ) | ||
690 | { | ||
691 | p = p->data.dir.entries; | ||
692 | sc->fi_pos = p; | ||
693 | } | ||
694 | /* abort on error */ | ||
632 | if (NULL != p->emsg) | 695 | if (NULL != p->emsg) |
633 | { | 696 | { |
634 | /* error with current file, abort all | 697 | /* error with current file, abort all |
@@ -653,15 +716,20 @@ do_upload (void *cls, | |||
653 | } | 716 | } |
654 | return; | 717 | return; |
655 | } | 718 | } |
719 | /* handle completion */ | ||
656 | if (NULL != p->chk_uri) | 720 | if (NULL != p->chk_uri) |
657 | { | 721 | { |
658 | /* move on to next file */ | ||
659 | if (NULL != p->next) | ||
660 | sc->fi_pos = p->next; | ||
661 | else | ||
662 | sc->fi_pos = p->dir; | ||
663 | /* upload of "p" complete, publish KBlocks! */ | 722 | /* upload of "p" complete, publish KBlocks! */ |
664 | publish_kblocks (sc, p); | 723 | GNUNET_FS_publish_ksk (sc->h, |
724 | p->keywords, | ||
725 | p->meta, | ||
726 | p->chk_uri, | ||
727 | p->expirationTime, | ||
728 | p->anonymity, | ||
729 | p->priority, | ||
730 | sc->options, | ||
731 | &publish_kblocks_cont, | ||
732 | sc); | ||
665 | return; | 733 | return; |
666 | } | 734 | } |
667 | if ( (!p->is_directory) && | 735 | if ( (!p->is_directory) && |
@@ -725,6 +793,7 @@ fip_signal_start(void *cls, | |||
725 | * (can be NULL, must be NULL if namespace is NULL) | 793 | * (can be NULL, must be NULL if namespace is NULL) |
726 | * @param nuid update-identifier that will be used for future updates | 794 | * @param nuid update-identifier that will be used for future updates |
727 | * (can be NULL, must be NULL if namespace or nid is NULL) | 795 | * (can be NULL, must be NULL if namespace or nid is NULL) |
796 | * @param options options for the publication | ||
728 | * @return context that can be used to control the publish operation | 797 | * @return context that can be used to control the publish operation |
729 | */ | 798 | */ |
730 | struct GNUNET_FS_PublishContext * | 799 | struct GNUNET_FS_PublishContext * |
@@ -733,16 +802,23 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, | |||
733 | struct GNUNET_FS_FileInformation *fi, | 802 | struct GNUNET_FS_FileInformation *fi, |
734 | struct GNUNET_FS_Namespace *namespace, | 803 | struct GNUNET_FS_Namespace *namespace, |
735 | const char *nid, | 804 | const char *nid, |
736 | const char *nuid) | 805 | const char *nuid, |
806 | enum GNUNET_FS_PublishOptions options) | ||
737 | { | 807 | { |
738 | struct GNUNET_FS_PublishContext *ret; | 808 | struct GNUNET_FS_PublishContext *ret; |
739 | struct GNUNET_FS_FileInformation *p; | ||
740 | struct GNUNET_DATASTORE_Handle *dsh; | 809 | struct GNUNET_DATASTORE_Handle *dsh; |
741 | 810 | ||
742 | dsh = GNUNET_DATASTORE_connect (h->cfg, | 811 | if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) |
743 | h->sched); | 812 | { |
744 | if (NULL == dsh) | 813 | dsh = GNUNET_DATASTORE_connect (h->cfg, |
745 | return NULL; | 814 | h->sched); |
815 | if (NULL == dsh) | ||
816 | return NULL; | ||
817 | } | ||
818 | else | ||
819 | { | ||
820 | dsh = NULL; | ||
821 | } | ||
746 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); | 822 | ret = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); |
747 | ret->dsh = dsh; | 823 | ret->dsh = dsh; |
748 | ret->h = h; | 824 | ret->h = h; |
@@ -763,12 +839,7 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, | |||
763 | GNUNET_FS_file_information_inspect (ret->fi, | 839 | GNUNET_FS_file_information_inspect (ret->fi, |
764 | &fip_signal_start, | 840 | &fip_signal_start, |
765 | ret); | 841 | ret); |
766 | /* find first leaf, DFS */ | 842 | ret->fi_pos = ret->fi; |
767 | p = ret->fi; | ||
768 | while ( (p->is_directory) && | ||
769 | (NULL != p->data.dir.entries) ) | ||
770 | p = p->data.dir.entries; | ||
771 | ret->fi_pos = p; | ||
772 | 843 | ||
773 | // FIXME: calculate space needed for "fi" | 844 | // FIXME: calculate space needed for "fi" |
774 | // and reserve as first task (then trigger | 845 | // and reserve as first task (then trigger |
@@ -851,29 +922,293 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *sc) | |||
851 | 922 | ||
852 | 923 | ||
853 | /** | 924 | /** |
854 | * Publish a KBlock on GNUnet. | 925 | * Context for the KSK publication. |
926 | */ | ||
927 | struct PublishKskContext | ||
928 | { | ||
929 | |||
930 | /** | ||
931 | * Keywords to use. | ||
932 | */ | ||
933 | struct GNUNET_FS_Uri *ksk_uri; | ||
934 | |||
935 | /** | ||
936 | * Global FS context. | ||
937 | */ | ||
938 | struct GNUNET_FS_Handle *h; | ||
939 | |||
940 | /** | ||
941 | * The master block that we are sending | ||
942 | * (in plaintext), has "mdsize+slen" more | ||
943 | * bytes than the struct would suggest. | ||
944 | */ | ||
945 | struct GNUNET_FS_KBlock *kb; | ||
946 | |||
947 | /** | ||
948 | * Buffer of the same size as "kb" for | ||
949 | * the encrypted version. | ||
950 | */ | ||
951 | struct GNUNET_FS_KBlock *cpy; | ||
952 | |||
953 | /** | ||
954 | * Handle to the datastore, NULL if we are just | ||
955 | * simulating. | ||
956 | */ | ||
957 | struct GNUNET_DATASTORE_Handle *dsh; | ||
958 | |||
959 | /** | ||
960 | * Function to call once we're done. | ||
961 | */ | ||
962 | GNUNET_FS_PublishContinuation cont; | ||
963 | |||
964 | /** | ||
965 | * Closure for cont. | ||
966 | */ | ||
967 | void *cont_cls; | ||
968 | |||
969 | /** | ||
970 | * When should the KBlocks expire? | ||
971 | */ | ||
972 | struct GNUNET_TIME_Absolute expirationTime; | ||
973 | |||
974 | /** | ||
975 | * Size of the serialized metadata. | ||
976 | */ | ||
977 | ssize_t mdsize; | ||
978 | |||
979 | /** | ||
980 | * Size of the (CHK) URI as a string. | ||
981 | */ | ||
982 | size_t slen; | ||
983 | |||
984 | /** | ||
985 | * Keyword that we are currently processing. | ||
986 | */ | ||
987 | unsigned int i; | ||
988 | |||
989 | /** | ||
990 | * Anonymity level for the KBlocks. | ||
991 | */ | ||
992 | unsigned int anonymity; | ||
993 | |||
994 | /** | ||
995 | * Priority for the KBlocks. | ||
996 | */ | ||
997 | unsigned int priority; | ||
998 | }; | ||
999 | |||
1000 | |||
1001 | /** | ||
1002 | * Continuation of "GNUNET_FS_publish_ksk" that performs | ||
1003 | * the actual publishing operation (iterating over all | ||
1004 | * of the keywords). | ||
1005 | * | ||
1006 | * @param cls closure of type "struct PublishKskContext*" | ||
1007 | * @param tc unused | ||
1008 | */ | ||
1009 | static void | ||
1010 | publish_ksk_cont (void *cls, | ||
1011 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1012 | |||
1013 | |||
1014 | /** | ||
1015 | * Function called by the datastore API with | ||
1016 | * the result from the PUT request. | ||
1017 | * | ||
1018 | * @param cls closure of type "struct PublishKskContext*" | ||
1019 | * @param success GNUNET_OK on success | ||
1020 | * @param msg error message (or NULL) | ||
1021 | */ | ||
1022 | static void | ||
1023 | kb_put_cont (void *cls, | ||
1024 | int success, | ||
1025 | const char *msg) | ||
1026 | { | ||
1027 | struct PublishKskContext *pkc = cls; | ||
1028 | |||
1029 | if (GNUNET_OK != success) | ||
1030 | { | ||
1031 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1032 | GNUNET_free (pkc->cpy); | ||
1033 | GNUNET_free (pkc->kb); | ||
1034 | pkc->cont (pkc->cont_cls, | ||
1035 | NULL, | ||
1036 | msg); | ||
1037 | GNUNET_FS_uri_destroy (pkc->ksk_uri); | ||
1038 | GNUNET_free (pkc); | ||
1039 | return; | ||
1040 | } | ||
1041 | GNUNET_SCHEDULER_add_continuation (pkc->h->sched, | ||
1042 | GNUNET_NO, | ||
1043 | &publish_ksk_cont, | ||
1044 | pkc, | ||
1045 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /** | ||
1050 | * Continuation of "GNUNET_FS_publish_ksk" that performs | ||
1051 | * the actual publishing operation (iterating over all | ||
1052 | * of the keywords). | ||
1053 | * | ||
1054 | * @param cls closure of type "struct PublishKskContext*" | ||
1055 | * @param tc unused | ||
1056 | */ | ||
1057 | static void | ||
1058 | publish_ksk_cont (void *cls, | ||
1059 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1060 | { | ||
1061 | struct PublishKskContext *pkc = cls; | ||
1062 | const char *keyword; | ||
1063 | GNUNET_HashCode key; | ||
1064 | GNUNET_HashCode query; | ||
1065 | struct GNUNET_CRYPTO_AesSessionKey skey; | ||
1066 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
1067 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; | ||
1068 | |||
1069 | |||
1070 | if ( (pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || | ||
1071 | (NULL == pkc->dsh) ) | ||
1072 | { | ||
1073 | if (NULL != pkc->dsh) | ||
1074 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1075 | GNUNET_free (pkc->cpy); | ||
1076 | GNUNET_free (pkc->kb); | ||
1077 | pkc->cont (pkc->cont_cls, | ||
1078 | pkc->ksk_uri, | ||
1079 | NULL); | ||
1080 | GNUNET_FS_uri_destroy (pkc->ksk_uri); | ||
1081 | GNUNET_free (pkc); | ||
1082 | return; | ||
1083 | } | ||
1084 | keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++]; | ||
1085 | /* first character of keyword indicates if it is | ||
1086 | mandatory or not -- ignore for hashing */ | ||
1087 | GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key); | ||
1088 | GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); | ||
1089 | GNUNET_CRYPTO_aes_encrypt (&pkc->kb[1], | ||
1090 | pkc->slen + pkc->mdsize, | ||
1091 | &skey, | ||
1092 | &iv, | ||
1093 | &pkc->cpy[1]); | ||
1094 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key); | ||
1095 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace); | ||
1096 | GNUNET_CRYPTO_hash (&pkc->cpy->keyspace, | ||
1097 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
1098 | &query); | ||
1099 | GNUNET_assert (GNUNET_OK == | ||
1100 | GNUNET_CRYPTO_rsa_sign (pk, | ||
1101 | &pkc->cpy->purpose, | ||
1102 | &pkc->cpy->signature)); | ||
1103 | GNUNET_CRYPTO_rsa_key_free (pk); | ||
1104 | GNUNET_DATASTORE_put (pkc->dsh, | ||
1105 | 0, | ||
1106 | &query, | ||
1107 | pkc->mdsize + | ||
1108 | sizeof (struct GNUNET_FS_KBlock) + | ||
1109 | pkc->slen, | ||
1110 | pkc->cpy, | ||
1111 | GNUNET_DATASTORE_BLOCKTYPE_KBLOCK, | ||
1112 | pkc->priority, | ||
1113 | pkc->anonymity, | ||
1114 | pkc->expirationTime, | ||
1115 | GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
1116 | &kb_put_cont, | ||
1117 | pkc); | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Publish a CHK under various keywords on GNUnet. | ||
855 | * | 1123 | * |
856 | * @param h handle to the file sharing subsystem | 1124 | * @param h handle to the file sharing subsystem |
857 | * @param keyword keyword to use | 1125 | * @param ksk_uri keywords to use |
858 | * @param meta metadata to use | 1126 | * @param meta metadata to use |
859 | * @param uri URI to refer to in the KBlock | 1127 | * @param uri URI to refer to in the KBlock |
860 | * @param expirationTime when the KBlock expires | 1128 | * @param expirationTime when the KBlock expires |
861 | * @param anonymity anonymity level for the KBlock | 1129 | * @param anonymity anonymity level for the KBlock |
862 | * @param priority priority for the KBlock | 1130 | * @param priority priority for the KBlock |
1131 | * @param options publication options | ||
1132 | * @param cont continuation | ||
1133 | * @param cont_cls closure for cont | ||
863 | */ | 1134 | */ |
864 | // FIXME: cps this one | ||
865 | void | 1135 | void |
866 | GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, | 1136 | GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, |
867 | const char *keyword, | 1137 | struct GNUNET_FS_Uri *ksk_uri, |
868 | struct GNUNET_CONTAINER_MetaData *meta, | 1138 | struct GNUNET_CONTAINER_MetaData *meta, |
869 | struct GNUNET_FS_Uri *uri, | 1139 | struct GNUNET_FS_Uri *uri, |
870 | struct GNUNET_TIME_Absolute expirationTime, | 1140 | struct GNUNET_TIME_Absolute expirationTime, |
871 | unsigned int anonymity, | 1141 | unsigned int anonymity, |
872 | unsigned int priority) | 1142 | unsigned int priority, |
1143 | enum GNUNET_FS_PublishOptions options, | ||
1144 | GNUNET_FS_PublishContinuation cont, | ||
1145 | void *cont_cls) | ||
873 | { | 1146 | { |
874 | // FIXME! | 1147 | struct PublishKskContext *pkc; |
875 | } | 1148 | char *uris; |
1149 | size_t size; | ||
1150 | char *kbe; | ||
1151 | |||
1152 | pkc = GNUNET_malloc (sizeof (struct PublishKskContext)); | ||
1153 | pkc->h = h; | ||
1154 | pkc->expirationTime = expirationTime; | ||
1155 | pkc->anonymity = anonymity; | ||
1156 | pkc->priority = priority; | ||
1157 | pkc->cont = cont; | ||
1158 | pkc->cont_cls = cont_cls; | ||
1159 | if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) | ||
1160 | { | ||
1161 | pkc->dsh = GNUNET_DATASTORE_connect (h->cfg, | ||
1162 | h->sched); | ||
1163 | if (pkc->dsh == NULL) | ||
1164 | { | ||
1165 | cont (cont_cls, NULL, _("Could not connect to datastore.")); | ||
1166 | GNUNET_free (pkc); | ||
1167 | return; | ||
1168 | } | ||
1169 | } | ||
1170 | pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta, | ||
1171 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | ||
1172 | GNUNET_assert (pkc->mdsize >= 0); | ||
1173 | uris = GNUNET_FS_uri_to_string (uri); | ||
1174 | pkc->slen = strlen (uris) + 1; | ||
1175 | size = pkc->mdsize + sizeof (struct GNUNET_FS_KBlock) + pkc->slen; | ||
1176 | if (size > MAX_KBLOCK_SIZE) | ||
1177 | { | ||
1178 | size = MAX_KBLOCK_SIZE; | ||
1179 | pkc->mdsize = size - sizeof (struct GNUNET_FS_KBlock) - pkc->slen; | ||
1180 | } | ||
1181 | pkc->kb = GNUNET_malloc (size); | ||
1182 | kbe = (char *) &pkc->kb[1]; | ||
1183 | memcpy (kbe, uris, pkc->slen); | ||
1184 | GNUNET_free (uris); | ||
1185 | pkc->mdsize = GNUNET_CONTAINER_meta_data_serialize (meta, | ||
1186 | &kbe[pkc->slen], | ||
1187 | pkc->mdsize, | ||
1188 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | ||
1189 | if (pkc->mdsize == -1) | ||
1190 | { | ||
1191 | GNUNET_break (0); | ||
1192 | GNUNET_free (uris); | ||
1193 | GNUNET_free (pkc->kb); | ||
1194 | if (pkc->dsh != NULL) | ||
1195 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1196 | cont (cont_cls, NULL, _("Internal error.")); | ||
1197 | GNUNET_free (pkc); | ||
1198 | return; | ||
1199 | } | ||
1200 | size = sizeof (struct GNUNET_FS_KBlock) + pkc->slen + pkc->mdsize; | ||
876 | 1201 | ||
1202 | pkc->cpy = GNUNET_malloc (size); | ||
1203 | pkc->cpy->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + pkc->mdsize + pkc->slen); | ||
1204 | pkc->cpy->purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK); | ||
1205 | pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); | ||
1206 | GNUNET_SCHEDULER_add_continuation (h->sched, | ||
1207 | GNUNET_NO, | ||
1208 | &publish_ksk_cont, | ||
1209 | pkc, | ||
1210 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1211 | } | ||
877 | 1212 | ||
878 | 1213 | ||
879 | /** | 1214 | /** |
@@ -888,8 +1223,10 @@ GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, | |||
888 | * @param expirationTime when the SBlock expires | 1223 | * @param expirationTime when the SBlock expires |
889 | * @param anonymity anonymity level for the SBlock | 1224 | * @param anonymity anonymity level for the SBlock |
890 | * @param priority priority for the SBlock | 1225 | * @param priority priority for the SBlock |
1226 | * @param options publication options | ||
1227 | * @param cont continuation | ||
1228 | * @param cont_cls closure for cont | ||
891 | */ | 1229 | */ |
892 | // FIXME: cps this one | ||
893 | void | 1230 | void |
894 | GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, | 1231 | GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, |
895 | struct GNUNET_FS_Namespace *namespace, | 1232 | struct GNUNET_FS_Namespace *namespace, |
@@ -899,9 +1236,104 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, | |||
899 | struct GNUNET_FS_Uri *uri, | 1236 | struct GNUNET_FS_Uri *uri, |
900 | struct GNUNET_TIME_Absolute expirationTime, | 1237 | struct GNUNET_TIME_Absolute expirationTime, |
901 | unsigned int anonymity, | 1238 | unsigned int anonymity, |
902 | unsigned int priority) | 1239 | unsigned int priority, |
1240 | enum GNUNET_FS_PublishOptions options, | ||
1241 | GNUNET_FS_PublishContinuation cont, | ||
1242 | void *cont_cls) | ||
903 | { | 1243 | { |
904 | // FIXME | 1244 | #if 0 |
1245 | struct GNUNET_ECRS_URI *uri; | ||
1246 | struct GNUNET_ClientServerConnection *sock; | ||
1247 | GNUNET_DatastoreValue *value; | ||
1248 | unsigned int size; | ||
1249 | unsigned int mdsize; | ||
1250 | struct GNUNET_RSA_PrivateKey *hk; | ||
1251 | GNUNET_EC_SBlock *sb; | ||
1252 | char *dstURI; | ||
1253 | char *destPos; | ||
1254 | GNUNET_HashCode hc; /* hash of thisId = key */ | ||
1255 | GNUNET_HashCode hc2; /* hash of hc = identifier */ | ||
1256 | int ret; | ||
1257 | unsigned int nidlen; | ||
1258 | |||
1259 | hk = read_namespace_key (cfg, pid); | ||
1260 | if (hk == NULL) | ||
1261 | return NULL; | ||
1262 | |||
1263 | /* THEN: construct GNUNET_EC_SBlock */ | ||
1264 | dstURI = GNUNET_ECRS_uri_to_string (dstU); | ||
1265 | mdsize = GNUNET_meta_data_get_serialized_size (md, GNUNET_SERIALIZE_PART); | ||
1266 | if (nextId == NULL) | ||
1267 | nextId = ""; | ||
1268 | nidlen = strlen (nextId) + 1; | ||
1269 | size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen; | ||
1270 | if (size > MAX_SBLOCK_SIZE) | ||
1271 | { | ||
1272 | size = MAX_SBLOCK_SIZE; | ||
1273 | mdsize = | ||
1274 | size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen); | ||
1275 | } | ||
1276 | value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size); | ||
1277 | sb = (GNUNET_EC_SBlock *) & value[1]; | ||
1278 | sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED); | ||
1279 | destPos = (char *) &sb[1]; | ||
1280 | memcpy (destPos, nextId, nidlen); | ||
1281 | destPos += nidlen; | ||
1282 | memcpy (destPos, dstURI, strlen (dstURI) + 1); | ||
1283 | destPos += strlen (dstURI) + 1; | ||
1284 | mdsize = GNUNET_meta_data_serialize (ectx, | ||
1285 | md, | ||
1286 | destPos, | ||
1287 | mdsize, GNUNET_SERIALIZE_PART); | ||
1288 | if (mdsize == -1) | ||
1289 | { | ||
1290 | GNUNET_GE_BREAK (ectx, 0); | ||
1291 | GNUNET_free (dstURI); | ||
1292 | GNUNET_RSA_free_key (hk); | ||
1293 | GNUNET_free (value); | ||
1294 | return NULL; | ||
1295 | } | ||
1296 | size = sizeof (GNUNET_EC_SBlock) + mdsize + strlen (dstURI) + 1 + nidlen; | ||
1297 | value->size = htonl (sizeof (GNUNET_DatastoreValue) + size); | ||
1298 | value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED); | ||
1299 | value->priority = htonl (priority); | ||
1300 | value->anonymity_level = htonl (anonymityLevel); | ||
1301 | value->expiration_time = GNUNET_htonll (expiration); | ||
1302 | GNUNET_hash (thisId, strlen (thisId), &hc); | ||
1303 | GNUNET_hash (&hc, sizeof (GNUNET_HashCode), &hc2); | ||
1304 | uri = GNUNET_malloc (sizeof (URI)); | ||
1305 | uri->type = sks; | ||
1306 | GNUNET_RSA_get_public_key (hk, &sb->subspace); | ||
1307 | GNUNET_hash (&sb->subspace, | ||
1308 | sizeof (GNUNET_RSA_PublicKey), &uri->data.sks.namespace); | ||
1309 | GNUNET_GE_BREAK (ectx, 0 == memcmp (&uri->data.sks.namespace, | ||
1310 | pid, sizeof (GNUNET_HashCode))); | ||
1311 | uri->data.sks.identifier = GNUNET_strdup (thisId); | ||
1312 | GNUNET_hash_xor (&hc2, &uri->data.sks.namespace, &sb->identifier); | ||
1313 | GNUNET_ECRS_encryptInPlace (&hc, &sb[1], size - sizeof (GNUNET_EC_SBlock)); | ||
1314 | GNUNET_GE_ASSERT (ectx, | ||
1315 | GNUNET_OK == GNUNET_RSA_sign (hk, | ||
1316 | size | ||
1317 | - | ||
1318 | sizeof | ||
1319 | (GNUNET_RSA_Signature) - | ||
1320 | sizeof | ||
1321 | (GNUNET_RSA_PublicKey) - | ||
1322 | sizeof (unsigned int), | ||
1323 | &sb->identifier, | ||
1324 | &sb->signature)); | ||
1325 | GNUNET_RSA_free_key (hk); | ||
1326 | sock = GNUNET_client_connection_create (ectx, cfg); | ||
1327 | ret = GNUNET_FS_insert (sock, value); | ||
1328 | if (ret != GNUNET_OK) | ||
1329 | { | ||
1330 | GNUNET_free (uri); | ||
1331 | uri = NULL; | ||
1332 | } | ||
1333 | GNUNET_client_connection_destroy (sock); | ||
1334 | GNUNET_free (value); | ||
1335 | GNUNET_free (dstURI); | ||
1336 | #endif | ||
905 | } | 1337 | } |
906 | 1338 | ||
907 | /* end of fs_publish.c */ | 1339 | /* end of fs_publish.c */ |
diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 7aac35146..b6b9199d0 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * @author Igor Wronsky | 26 | * @author Igor Wronsky |
27 | * | 27 | * |
28 | * TODO: | 28 | * TODO: |
29 | * - support for some options is still missing (uri argument, simulate) | 29 | * - support for some options is still missing (uri argument) |
30 | * - progress callbacks not implemented (and need verbosity option) | 30 | * - progress callbacks not implemented (and need verbosity option) |
31 | * - clean shutdown is not implemented (stop ctx, etc.) | 31 | * - clean shutdown is not implemented (stop ctx, etc.) |
32 | */ | 32 | */ |
@@ -385,7 +385,10 @@ run (void *cls, | |||
385 | fi, | 385 | fi, |
386 | namespace, | 386 | namespace, |
387 | this_id, | 387 | this_id, |
388 | next_id); | 388 | next_id, |
389 | (do_simulate) | ||
390 | ? GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY | ||
391 | : GNUNET_FS_PUBLISH_OPTION_NONE); | ||
389 | } | 392 | } |
390 | 393 | ||
391 | 394 | ||