aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_download.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/fs_download.c')
-rw-r--r--src/fs/fs_download.c736
1 files changed, 364 insertions, 372 deletions
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
index 2d64bba11..59821f8a5 100644
--- a/src/fs/fs_download.c
+++ b/src/fs/fs_download.c
@@ -37,15 +37,13 @@ static int
37is_recursive_download (struct GNUNET_FS_DownloadContext *dc) 37is_recursive_download (struct GNUNET_FS_DownloadContext *dc)
38{ 38{
39 return (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE)) && 39 return (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE)) &&
40 ( (GNUNET_YES == 40 ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (dc->meta)) ||
41 GNUNET_FS_meta_data_test_for_directory (dc->meta)) || 41 ((NULL == dc->meta) &&
42 ( (NULL == dc->meta) && 42 ((NULL == dc->filename) ||
43 ( (NULL == dc->filename) || 43 ((strlen (dc->filename) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
44 ( (strlen (dc->filename) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && 44 (NULL != strstr (dc->filename + strlen (dc->filename) -
45 (NULL != 45 strlen (GNUNET_FS_DIRECTORY_EXT),
46 strstr (dc->filename + strlen (dc->filename) - 46 GNUNET_FS_DIRECTORY_EXT))))));
47 strlen (GNUNET_FS_DIRECTORY_EXT),
48 GNUNET_FS_DIRECTORY_EXT)) ) ) ) );
49} 47}
50 48
51 49
@@ -69,9 +67,9 @@ static uint64_t
69compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth) 67compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth)
70{ 68{
71 unsigned int i; 69 unsigned int i;
72 uint64_t lsize; /* what is the size of all IBlocks for depth "i"? */ 70 uint64_t lsize; /* what is the size of all IBlocks for depth "i"? */
73 uint64_t loff; /* where do IBlocks for depth "i" start? */ 71 uint64_t loff; /* where do IBlocks for depth "i" start? */
74 unsigned int ioff; /* which IBlock corresponds to "off" at depth "i"? */ 72 unsigned int ioff; /* which IBlock corresponds to "off" at depth "i"? */
75 73
76 if (0 == depth) 74 if (0 == depth)
77 return off; 75 return off;
@@ -79,8 +77,7 @@ compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth)
79 * to full DBLOCK_SIZE */ 77 * to full DBLOCK_SIZE */
80 loff = ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * DBLOCK_SIZE; 78 loff = ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * DBLOCK_SIZE;
81 lsize = 79 lsize =
82 ((fsize + DBLOCK_SIZE - 80 ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * sizeof (struct ContentHashKey);
83 1) / DBLOCK_SIZE) * sizeof (struct ContentHashKey);
84 GNUNET_assert (0 == (off % DBLOCK_SIZE)); 81 GNUNET_assert (0 == (off % DBLOCK_SIZE));
85 ioff = (off / DBLOCK_SIZE); 82 ioff = (off / DBLOCK_SIZE);
86 for (i = 1; i < depth; i++) 83 for (i = 1; i < depth; i++)
@@ -109,19 +106,19 @@ GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi,
109 pi->value.download.dc = dc; 106 pi->value.download.dc = dc;
110 pi->value.download.cctx = dc->client_info; 107 pi->value.download.cctx = dc->client_info;
111 pi->value.download.pctx = 108 pi->value.download.pctx =
112 (NULL == dc->parent) ? NULL : dc->parent->client_info; 109 (NULL == dc->parent) ? NULL : dc->parent->client_info;
113 pi->value.download.sctx = 110 pi->value.download.sctx =
114 (NULL == dc->search) ? NULL : dc->search->client_info; 111 (NULL == dc->search) ? NULL : dc->search->client_info;
115 pi->value.download.uri = dc->uri; 112 pi->value.download.uri = dc->uri;
116 pi->value.download.filename = dc->filename; 113 pi->value.download.filename = dc->filename;
117 pi->value.download.size = dc->length; 114 pi->value.download.size = dc->length;
118 /* FIXME: Fix duration calculation to account for pauses */ 115 /* FIXME: Fix duration calculation to account for pauses */
119 pi->value.download.duration = 116 pi->value.download.duration =
120 GNUNET_TIME_absolute_get_duration (dc->start_time); 117 GNUNET_TIME_absolute_get_duration (dc->start_time);
121 pi->value.download.completed = dc->completed; 118 pi->value.download.completed = dc->completed;
122 pi->value.download.anonymity = dc->anonymity; 119 pi->value.download.anonymity = dc->anonymity;
123 pi->value.download.eta = 120 pi->value.download.eta =
124 GNUNET_TIME_calculate_eta (dc->start_time, dc->completed, dc->length); 121 GNUNET_TIME_calculate_eta (dc->start_time, dc->completed, dc->length);
125 pi->value.download.is_active = (NULL == dc->mq) ? GNUNET_NO : GNUNET_YES; 122 pi->value.download.is_active = (NULL == dc->mq) ? GNUNET_NO : GNUNET_YES;
126 pi->fsh = dc->h; 123 pi->fsh = dc->h;
127 if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) 124 if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
@@ -181,7 +178,6 @@ struct ProcessResultClosure
181 * how often did we transmit the query? 178 * how often did we transmit the query?
182 */ 179 */
183 uint32_t num_transmissions; 180 uint32_t num_transmissions;
184
185}; 181};
186 182
187 183
@@ -196,7 +192,7 @@ struct ProcessResultClosure
196 */ 192 */
197static int 193static int
198process_result_with_request (void *cls, 194process_result_with_request (void *cls,
199 const struct GNUNET_HashCode * key, 195 const struct GNUNET_HashCode *key,
200 void *value); 196 void *value);
201 197
202 198
@@ -216,8 +212,10 @@ process_result_with_request (void *cls,
216static int 212static int
217encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, 213encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc,
218 const struct ContentHashKey *chk, 214 const struct ContentHashKey *chk,
219 struct DownloadRequest *dr, const char *block, 215 struct DownloadRequest *dr,
220 size_t len, int do_store) 216 const char *block,
217 size_t len,
218 int do_store)
221{ 219{
222 struct ProcessResultClosure prc; 220 struct ProcessResultClosure prc;
223 char enc[len]; 221 char enc[len];
@@ -237,17 +235,18 @@ encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc,
237 GNUNET_break_op (0); 235 GNUNET_break_op (0);
238 return GNUNET_SYSERR; 236 return GNUNET_SYSERR;
239 } 237 }
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 238 GNUNET_log (
241 "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n", 239 GNUNET_ERROR_TYPE_DEBUG,
242 (unsigned int) len, 240 "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n",
243 dc->filename, (unsigned long long) dr->offset); 241 (unsigned int) len,
242 dc->filename,
243 (unsigned long long) dr->offset);
244 /* already got it! */ 244 /* already got it! */
245 prc.dc = dc; 245 prc.dc = dc;
246 prc.data = enc; 246 prc.data = enc;
247 prc.size = len; 247 prc.size = len;
248 prc.type = 248 prc.type = (0 == dr->depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK
249 (0 == 249 : GNUNET_BLOCK_TYPE_FS_IBLOCK;
250 dr->depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK : GNUNET_BLOCK_TYPE_FS_IBLOCK;
251 prc.query = chk->query; 250 prc.query = chk->query;
252 prc.do_store = do_store; 251 prc.do_store = do_store;
253 prc.last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS; 252 prc.last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
@@ -306,8 +305,10 @@ full_recursive_download (struct GNUNET_FS_DownloadContext *dc)
306 size = (size_t) size64; 305 size = (size_t) size64;
307 if (size64 != (uint64_t) size) 306 if (size64 != (uint64_t) size)
308 { 307 {
309 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 308 GNUNET_log (
310 _("Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems\n")); 309 GNUNET_ERROR_TYPE_ERROR,
310 _ (
311 "Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems\n"));
311 return; 312 return;
312 } 313 }
313 if (NULL != dc->filename) 314 if (NULL != dc->filename)
@@ -324,15 +325,12 @@ full_recursive_download (struct GNUNET_FS_DownloadContext *dc)
324 GNUNET_DISK_PERM_NONE); 325 GNUNET_DISK_PERM_NONE);
325 } 326 }
326 if (NULL == h) 327 if (NULL == h)
327 return; /* oops */ 328 return; /* oops */
328 data = GNUNET_DISK_file_map (h, 329 data = GNUNET_DISK_file_map (h, &m, GNUNET_DISK_MAP_TYPE_READ, size);
329 &m,
330 GNUNET_DISK_MAP_TYPE_READ,
331 size);
332 if (NULL == data) 330 if (NULL == data)
333 { 331 {
334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 332 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
335 _("Directory too large for system address space\n")); 333 _ ("Directory too large for system address space\n"));
336 } 334 }
337 else 335 else
338 { 336 {
@@ -343,16 +341,18 @@ full_recursive_download (struct GNUNET_FS_DownloadContext *dc)
343 &trigger_recursive_download, 341 &trigger_recursive_download,
344 dc)) 342 dc))
345 { 343 {
346 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 344 GNUNET_log (
347 _("Failed to access full directroy contents of `%s' for recursive download\n"), 345 GNUNET_ERROR_TYPE_WARNING,
348 dc->filename); 346 _ (
347 "Failed to access full directroy contents of `%s' for recursive download\n"),
348 dc->filename);
349 } 349 }
350 GNUNET_DISK_file_unmap (m); 350 GNUNET_DISK_file_unmap (m);
351 } 351 }
352 GNUNET_DISK_file_close (h); 352 GNUNET_DISK_file_close (h);
353 if (NULL == dc->filename) 353 if (NULL == dc->filename)
354 { 354 {
355 if (0 != UNLINK (dc->temp_filename)) 355 if (0 != unlink (dc->temp_filename))
356 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 356 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
357 "unlink", 357 "unlink",
358 dc->temp_filename); 358 dc->temp_filename);
@@ -384,12 +384,10 @@ check_completed (struct GNUNET_FS_DownloadContext *dc)
384 /* then, check if children are done already */ 384 /* then, check if children are done already */
385 for (pos = dc->child_head; NULL != pos; pos = pos->next) 385 for (pos = dc->child_head; NULL != pos; pos = pos->next)
386 { 386 {
387 if ( (NULL == pos->emsg) && 387 if ((NULL == pos->emsg) && (pos->completed < pos->length))
388 (pos->completed < pos->length) ) 388 return; /* not done yet */
389 return; /* not done yet */ 389 if ((NULL != pos->child_head) && (pos->has_finished != GNUNET_YES))
390 if ( (NULL != pos->child_head) && 390 return; /* not transitively done yet */
391 (pos->has_finished != GNUNET_YES) )
392 return; /* not transitively done yet */
393 } 391 }
394 /* All of our children are done, so mark this download done */ 392 /* All of our children are done, so mark this download done */
395 dc->has_finished = GNUNET_YES; 393 dc->has_finished = GNUNET_YES;
@@ -432,7 +430,9 @@ check_completed (struct GNUNET_FS_DownloadContext *dc)
432 */ 430 */
433static void 431static void
434try_match_block (struct GNUNET_FS_DownloadContext *dc, 432try_match_block (struct GNUNET_FS_DownloadContext *dc,
435 struct DownloadRequest *dr, const char *data, size_t data_len) 433 struct DownloadRequest *dr,
434 const char *data,
435 size_t data_len)
436{ 436{
437 struct GNUNET_FS_ProgressInfo pi; 437 struct GNUNET_FS_ProgressInfo pi;
438 unsigned int i; 438 unsigned int i;
@@ -455,8 +455,8 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
455 return; 455 return;
456 if (dr->depth > 0) 456 if (dr->depth > 0)
457 { 457 {
458 if ( (dc->offset > 0) || 458 if ((dc->offset > 0) ||
459 (dc->length < GNUNET_ntohll (dc->uri->data.chk.file_length)) ) 459 (dc->length < GNUNET_ntohll (dc->uri->data.chk.file_length)))
460 { 460 {
461 /* NOTE: this test is not tight, but should suffice; the issue 461 /* NOTE: this test is not tight, but should suffice; the issue
462 here is that 'dr->num_children' may inherently only specify a 462 here is that 'dr->num_children' may inherently only specify a
@@ -485,16 +485,13 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
485 else 485 else
486 { 486 {
487 if (dr->offset > data_len) 487 if (dr->offset > data_len)
488 return; /* oops */ 488 return; /* oops */
489 dlen = GNUNET_MIN (data_len - dr->offset, DBLOCK_SIZE); 489 dlen = GNUNET_MIN (data_len - dr->offset, DBLOCK_SIZE);
490 } 490 }
491 GNUNET_CRYPTO_hash (&data[dr->offset], dlen, &in_chk.key); 491 GNUNET_CRYPTO_hash (&data[dr->offset], dlen, &in_chk.key);
492 GNUNET_CRYPTO_hash_to_aes_key (&in_chk.key, &sk, &iv); 492 GNUNET_CRYPTO_hash_to_aes_key (&in_chk.key, &sk, &iv);
493 if (-1 == GNUNET_CRYPTO_symmetric_encrypt (&data[dr->offset], 493 if (-1 ==
494 dlen, 494 GNUNET_CRYPTO_symmetric_encrypt (&data[dr->offset], dlen, &sk, &iv, enc))
495 &sk,
496 &iv,
497 enc))
498 { 495 {
499 GNUNET_break (0); 496 GNUNET_break (0);
500 return; 497 return;
@@ -507,9 +504,7 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
507 dr->state = BRS_RECONSTRUCT_META_UP; 504 dr->state = BRS_RECONSTRUCT_META_UP;
508 break; 505 break;
509 case BRS_CHK_SET: 506 case BRS_CHK_SET:
510 if (0 != memcmp (&in_chk, 507 if (0 != memcmp (&in_chk, &dr->chk, sizeof (struct ContentHashKey)))
511 &dr->chk,
512 sizeof (struct ContentHashKey)))
513 { 508 {
514 /* other peer provided bogus meta data */ 509 /* other peer provided bogus meta data */
515 GNUNET_break_op (0); 510 GNUNET_break_op (0);
@@ -521,17 +516,17 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
521 { 516 {
522 fh = GNUNET_DISK_file_open (fn, 517 fh = GNUNET_DISK_file_open (fn,
523 GNUNET_DISK_OPEN_READWRITE | 518 GNUNET_DISK_OPEN_READWRITE |
524 GNUNET_DISK_OPEN_CREATE | 519 GNUNET_DISK_OPEN_CREATE |
525 GNUNET_DISK_OPEN_TRUNCATE, 520 GNUNET_DISK_OPEN_TRUNCATE,
526 GNUNET_DISK_PERM_USER_READ | 521 GNUNET_DISK_PERM_USER_READ |
527 GNUNET_DISK_PERM_USER_WRITE | 522 GNUNET_DISK_PERM_USER_WRITE |
528 GNUNET_DISK_PERM_GROUP_READ | 523 GNUNET_DISK_PERM_GROUP_READ |
529 GNUNET_DISK_PERM_OTHER_READ); 524 GNUNET_DISK_PERM_OTHER_READ);
530 if (NULL == fh) 525 if (NULL == fh)
531 { 526 {
532 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); 527 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
533 GNUNET_asprintf (&dc->emsg, 528 GNUNET_asprintf (&dc->emsg,
534 _("Failed to open file `%s' for writing"), 529 _ ("Failed to open file `%s' for writing"),
535 fn); 530 fn);
536 GNUNET_DISK_file_close (fh); 531 GNUNET_DISK_file_close (fh);
537 dr->state = BRS_ERROR; 532 dr->state = BRS_ERROR;
@@ -543,7 +538,8 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
543 if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len)) 538 if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len))
544 { 539 {
545 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn); 540 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
546 GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"), 541 GNUNET_asprintf (&dc->emsg,
542 _ ("Failed to open file `%s' for writing"),
547 fn); 543 fn);
548 GNUNET_DISK_file_close (fh); 544 GNUNET_DISK_file_close (fh);
549 dr->state = BRS_ERROR; 545 dr->state = BRS_ERROR;
@@ -564,13 +560,14 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
564 pi.value.download.specifics.progress.data_len = dlen; 560 pi.value.download.specifics.progress.data_len = dlen;
565 pi.value.download.specifics.progress.depth = 0; 561 pi.value.download.specifics.progress.depth = 0;
566 pi.value.download.specifics.progress.respect_offered = 0; 562 pi.value.download.specifics.progress.respect_offered = 0;
567 pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; 563 pi.value.download.specifics.progress.block_download_duration =
564 GNUNET_TIME_UNIT_ZERO;
568 GNUNET_FS_download_make_status_ (&pi, dc); 565 GNUNET_FS_download_make_status_ (&pi, dc);
569 if ((NULL != dc->filename) && 566 if ((NULL != dc->filename) &&
570 (0 != 567 (0 != truncate (dc->filename,
571 TRUNCATE (dc->filename, 568 GNUNET_ntohll (dc->uri->data.chk.file_length))))
572 GNUNET_ntohll (dc->uri->data.chk.file_length)))) 569 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
573 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", 570 "truncate",
574 dc->filename); 571 dc->filename);
575 check_completed (dc); 572 check_completed (dc);
576 break; 573 break;
@@ -601,25 +598,27 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc,
601 * @return 0 to continue extracting, 1 to abort 598 * @return 0 to continue extracting, 1 to abort
602 */ 599 */
603static int 600static int
604match_full_data (void *cls, const char *plugin_name, 601match_full_data (void *cls,
605 enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, 602 const char *plugin_name,
606 const char *data_mime_type, const char *data, size_t data_len) 603 enum EXTRACTOR_MetaType type,
604 enum EXTRACTOR_MetaFormat format,
605 const char *data_mime_type,
606 const char *data,
607 size_t data_len)
607{ 608{
608 struct GNUNET_FS_DownloadContext *dc = cls; 609 struct GNUNET_FS_DownloadContext *dc = cls;
609 610
610 if (EXTRACTOR_METATYPE_GNUNET_FULL_DATA != type) 611 if (EXTRACTOR_METATYPE_GNUNET_FULL_DATA != type)
611 return 0; 612 return 0;
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u bytes of FD!\n", 613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
614 "Found %u bytes of FD!\n",
613 (unsigned int) data_len); 615 (unsigned int) data_len);
614 if (GNUNET_FS_uri_chk_get_file_size (dc->uri) != data_len) 616 if (GNUNET_FS_uri_chk_get_file_size (dc->uri) != data_len)
615 { 617 {
616 GNUNET_break_op (0); 618 GNUNET_break_op (0);
617 return 1; /* bogus meta data */ 619 return 1; /* bogus meta data */
618 } 620 }
619 try_match_block (dc, 621 try_match_block (dc, dc->top_request, data, data_len);
620 dc->top_request,
621 data,
622 data_len);
623 return 1; 622 return 1;
624} 623}
625 624
@@ -644,8 +643,7 @@ propagate_up (struct DownloadRequest *dr)
644 for (i = 0; i < dr->num_children; i++) 643 for (i = 0; i < dr->num_children; i++)
645 if (dr->children[i]->state != BRS_DOWNLOAD_UP) 644 if (dr->children[i]->state != BRS_DOWNLOAD_UP)
646 break; 645 break;
647 } 646 } while (i == dr->num_children);
648 while (i == dr->num_children);
649} 647}
650 648
651 649
@@ -682,20 +680,20 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc,
682 GNUNET_assert (len <= DBLOCK_SIZE); 680 GNUNET_assert (len <= DBLOCK_SIZE);
683 off = compute_disk_offset (total, dr->offset, dr->depth); 681 off = compute_disk_offset (total, dr->offset, dr->depth);
684 if (dc->old_file_size < off + len) 682 if (dc->old_file_size < off + len)
685 return; /* failure */ 683 return; /* failure */
686 if (off != GNUNET_DISK_file_seek (dc->rfh, off, GNUNET_DISK_SEEK_SET)) 684 if (off != GNUNET_DISK_file_seek (dc->rfh, off, GNUNET_DISK_SEEK_SET))
687 { 685 {
688 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "seek", dc->filename); 686 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "seek", dc->filename);
689 return; /* failure */ 687 return; /* failure */
690 } 688 }
691 if (len != GNUNET_DISK_file_read (dc->rfh, block, len)) 689 if (len != GNUNET_DISK_file_read (dc->rfh, block, len))
692 { 690 {
693 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", dc->filename); 691 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", dc->filename);
694 return; /* failure */ 692 return; /* failure */
695 } 693 }
696 GNUNET_CRYPTO_hash (block, len, &key); 694 GNUNET_CRYPTO_hash (block, len, &key);
697 if (0 != memcmp (&key, &dr->chk.key, sizeof (struct GNUNET_HashCode))) 695 if (0 != memcmp (&key, &dr->chk.key, sizeof (struct GNUNET_HashCode)))
698 return; /* mismatch */ 696 return; /* mismatch */
699 if (GNUNET_OK != 697 if (GNUNET_OK !=
700 encrypt_existing_match (dc, &dr->chk, dr, block, len, GNUNET_NO)) 698 encrypt_existing_match (dc, &dr->chk, dr, block, len, GNUNET_NO))
701 { 699 {
@@ -728,10 +726,10 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc,
728 try_top_down_reconstruction (dc, drc); 726 try_top_down_reconstruction (dc, drc);
729 } 727 }
730 if (BRS_DOWNLOAD_UP != drc->state) 728 if (BRS_DOWNLOAD_UP != drc->state)
731 up_done = GNUNET_NO; /* children not all done */ 729 up_done = GNUNET_NO; /* children not all done */
732 } 730 }
733 if (GNUNET_YES == up_done) 731 if (GNUNET_YES == up_done)
734 propagate_up (dr); /* children all done (or no children...) */ 732 propagate_up (dr); /* children all done (or no children...) */
735} 733}
736 734
737 735
@@ -744,17 +742,14 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc,
744 * @return #GNUNET_OK 742 * @return #GNUNET_OK
745 */ 743 */
746static int 744static int
747retry_entry (void *cls, 745retry_entry (void *cls, const struct GNUNET_HashCode *key, void *entry)
748 const struct GNUNET_HashCode *key,
749 void *entry)
750{ 746{
751 struct GNUNET_FS_DownloadContext *dc = cls; 747 struct GNUNET_FS_DownloadContext *dc = cls;
752 struct DownloadRequest *dr = entry; 748 struct DownloadRequest *dr = entry;
753 struct SearchMessage *sm; 749 struct SearchMessage *sm;
754 struct GNUNET_MQ_Envelope *env; 750 struct GNUNET_MQ_Envelope *env;
755 751
756 env = GNUNET_MQ_msg (sm, 752 env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_FS_START_SEARCH);
757 GNUNET_MESSAGE_TYPE_FS_START_SEARCH);
758 if (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY)) 753 if (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY))
759 sm->options = htonl (GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY); 754 sm->options = htonl (GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY);
760 else 755 else
@@ -766,8 +761,7 @@ retry_entry (void *cls,
766 sm->anonymity_level = htonl (dc->anonymity); 761 sm->anonymity_level = htonl (dc->anonymity);
767 sm->target = dc->target; 762 sm->target = dc->target;
768 sm->query = dr->chk.query; 763 sm->query = dr->chk.query;
769 GNUNET_MQ_send (dc->mq, 764 GNUNET_MQ_send (dc->mq, env);
770 env);
771 return GNUNET_OK; 765 return GNUNET_OK;
772} 766}
773 767
@@ -817,20 +811,17 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
817 (unsigned long long) dr->offset, 811 (unsigned long long) dr->offset,
818 dr->depth, 812 dr->depth,
819 GNUNET_h2s (&dr->chk.query)); 813 GNUNET_h2s (&dr->chk.query));
820 if (GNUNET_NO != 814 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains_value (dc->active,
821 GNUNET_CONTAINER_multihashmap_contains_value (dc->active, 815 &dr->chk.query,
822 &dr->chk.query, 816 dr))
823 dr)) 817 return; /* already active */
824 return; /* already active */
825 GNUNET_CONTAINER_multihashmap_put (dc->active, 818 GNUNET_CONTAINER_multihashmap_put (dc->active,
826 &dr->chk.query, 819 &dr->chk.query,
827 dr, 820 dr,
828 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 821 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
829 if (NULL == dc->mq) 822 if (NULL == dc->mq)
830 return; /* download not active */ 823 return; /* download not active */
831 retry_entry (dc, 824 retry_entry (dc, &dr->chk.query, dr);
832 &dr->chk.query,
833 dr);
834} 825}
835 826
836 827
@@ -867,7 +858,7 @@ trigger_recursive_download (void *cls,
867 char *sfn; 858 char *sfn;
868 859
869 if (NULL == uri) 860 if (NULL == uri)
870 return; /* entry for the directory itself */ 861 return; /* entry for the directory itself */
871 cpos = dc->child_head; 862 cpos = dc->child_head;
872 while (NULL != cpos) 863 while (NULL != cpos)
873 { 864 {
@@ -877,7 +868,7 @@ trigger_recursive_download (void *cls,
877 cpos = cpos->next; 868 cpos = cpos->next;
878 } 869 }
879 if (NULL != cpos) 870 if (NULL != cpos)
880 return; /* already exists */ 871 return; /* already exists */
881 fn = NULL; 872 fn = NULL;
882 if (NULL == filename) 873 if (NULL == filename)
883 { 874 {
@@ -892,7 +883,9 @@ trigger_recursive_download (void *cls,
892 { 883 {
893 ext = fn; 884 ext = fn;
894 us = GNUNET_FS_uri_to_string (uri); 885 us = GNUNET_FS_uri_to_string (uri);
895 GNUNET_asprintf (&fn, "%s%s", &us[strlen (GNUNET_FS_URI_CHK_PREFIX)], 886 GNUNET_asprintf (&fn,
887 "%s%s",
888 &us[strlen (GNUNET_FS_URI_CHK_PREFIX)],
896 ext); 889 ext);
897 GNUNET_free (ext); 890 GNUNET_free (ext);
898 GNUNET_free (us); 891 GNUNET_free (us);
@@ -920,25 +913,28 @@ trigger_recursive_download (void *cls,
920 else 913 else
921 { 914 {
922 dn = GNUNET_strdup (dc->filename); 915 dn = GNUNET_strdup (dc->filename);
923 GNUNET_break ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && 916 GNUNET_break (
924 (NULL != 917 (strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
925 strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT), 918 (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT),
926 GNUNET_FS_DIRECTORY_EXT))); 919 GNUNET_FS_DIRECTORY_EXT)));
927 sfn = GNUNET_strdup (filename); 920 sfn = GNUNET_strdup (filename);
928 while ((strlen (sfn) > 0) && ('/' == filename[strlen (sfn) - 1])) 921 while ((strlen (sfn) > 0) && ('/' == filename[strlen (sfn) - 1]))
929 sfn[strlen (sfn) - 1] = '\0'; 922 sfn[strlen (sfn) - 1] = '\0';
930 if ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && 923 if ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
931 (NULL != 924 (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT),
932 strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT), 925 GNUNET_FS_DIRECTORY_EXT)))
933 GNUNET_FS_DIRECTORY_EXT)))
934 dn[strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT)] = '\0'; 926 dn[strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT)] = '\0';
935 if ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) && 927 if ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) &&
936 ((strlen (filename) < strlen (GNUNET_FS_DIRECTORY_EXT)) || 928 ((strlen (filename) < strlen (GNUNET_FS_DIRECTORY_EXT)) ||
937 (NULL == 929 (NULL == strstr (filename + strlen (filename) -
938 strstr (filename + strlen (filename) - 930 strlen (GNUNET_FS_DIRECTORY_EXT),
939 strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT)))) 931 GNUNET_FS_DIRECTORY_EXT))))
940 { 932 {
941 GNUNET_asprintf (&full_name, "%s%s%s%s", dn, DIR_SEPARATOR_STR, sfn, 933 GNUNET_asprintf (&full_name,
934 "%s%s%s%s",
935 dn,
936 DIR_SEPARATOR_STR,
937 sfn,
942 GNUNET_FS_DIRECTORY_EXT); 938 GNUNET_FS_DIRECTORY_EXT);
943 } 939 }
944 else 940 else
@@ -952,8 +948,8 @@ trigger_recursive_download (void *cls,
952 (GNUNET_OK != GNUNET_DISK_directory_create_for_file (full_name))) 948 (GNUNET_OK != GNUNET_DISK_directory_create_for_file (full_name)))
953 { 949 {
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 _ 951 _ (
956 ("Failed to create directory for recursive download of `%s'\n"), 952 "Failed to create directory for recursive download of `%s'\n"),
957 full_name); 953 full_name);
958 GNUNET_free (full_name); 954 GNUNET_free (full_name);
959 GNUNET_free_non_null (fn); 955 GNUNET_free_non_null (fn);
@@ -964,8 +960,8 @@ trigger_recursive_download (void *cls,
964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 "Triggering recursive download of size %llu with %u bytes MD\n", 961 "Triggering recursive download of size %llu with %u bytes MD\n",
966 (unsigned long long) GNUNET_FS_uri_chk_get_file_size (uri), 962 (unsigned long long) GNUNET_FS_uri_chk_get_file_size (uri),
967 (unsigned int) 963 (unsigned int) GNUNET_CONTAINER_meta_data_get_serialized_size (
968 GNUNET_CONTAINER_meta_data_get_serialized_size (meta)); 964 meta));
969 GNUNET_FS_download_start (dc->h, 965 GNUNET_FS_download_start (dc->h,
970 uri, 966 uri,
971 meta, 967 meta,
@@ -1029,26 +1025,29 @@ process_result_with_request (void *cls,
1029 int i; 1025 int i;
1030 struct ContentHashKey *chkarr; 1026 struct ContentHashKey *chkarr;
1031 1027
1032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1028 GNUNET_log (
1033 "Received %u byte block `%s' matching pending request at depth %u and offset %llu/%llu\n", 1029 GNUNET_ERROR_TYPE_DEBUG,
1034 (unsigned int) prc->size, 1030 "Received %u byte block `%s' matching pending request at depth %u and offset %llu/%llu\n",
1035 GNUNET_h2s (key), 1031 (unsigned int) prc->size,
1036 dr->depth, 1032 GNUNET_h2s (key),
1037 (unsigned long long) dr->offset, 1033 dr->depth,
1038 (unsigned long long) GNUNET_ntohll (dc->uri->data. 1034 (unsigned long long) dr->offset,
1039 chk.file_length)); 1035 (unsigned long long) GNUNET_ntohll (dc->uri->data.chk.file_length));
1040 bs = GNUNET_FS_tree_calculate_block_size (GNUNET_ntohll 1036 bs = GNUNET_FS_tree_calculate_block_size (GNUNET_ntohll (
1041 (dc->uri->data.chk.file_length), 1037 dc->uri->data.chk.file_length),
1042 dr->offset, dr->depth); 1038 dr->offset,
1039 dr->depth);
1043 if (prc->size != bs) 1040 if (prc->size != bs)
1044 { 1041 {
1045 GNUNET_asprintf (&dc->emsg, 1042 GNUNET_asprintf (
1046 _ 1043 &dc->emsg,
1047 ("Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)"), 1044 _ (
1048 bs, dr->depth, (unsigned long long) dr->offset, 1045 "Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)"),
1049 (unsigned long long) GNUNET_ntohll (dc->uri->data. 1046 bs,
1050 chk.file_length), 1047 dr->depth,
1051 prc->size); 1048 (unsigned long long) dr->offset,
1049 (unsigned long long) GNUNET_ntohll (dc->uri->data.chk.file_length),
1050 prc->size);
1052 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", dc->emsg); 1051 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", dc->emsg);
1053 while (NULL != dr->parent) 1052 while (NULL != dr->parent)
1054 { 1053 {
@@ -1059,69 +1058,61 @@ process_result_with_request (void *cls,
1059 goto signal_error; 1058 goto signal_error;
1060 } 1059 }
1061 1060
1062 (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, 1061 (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &prc->query, dr);
1063 &prc->query, 1062 GNUNET_CRYPTO_hash_to_aes_key (&dr->chk.key, &skey, &iv);
1064 dr); 1063 if (-1 ==
1065 GNUNET_CRYPTO_hash_to_aes_key (&dr->chk.key, 1064 GNUNET_CRYPTO_symmetric_decrypt (prc->data, prc->size, &skey, &iv, pt))
1066 &skey,
1067 &iv);
1068 if (-1 == GNUNET_CRYPTO_symmetric_decrypt (prc->data,
1069 prc->size,
1070 &skey,
1071 &iv,
1072 pt))
1073 { 1065 {
1074 GNUNET_break (0); 1066 GNUNET_break (0);
1075 dc->emsg = GNUNET_strdup (_("internal error decrypting content")); 1067 dc->emsg = GNUNET_strdup (_ ("internal error decrypting content"));
1076 goto signal_error; 1068 goto signal_error;
1077 } 1069 }
1078 off = 1070 off = compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length),
1079 compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length), 1071 dr->offset,
1080 dr->offset, 1072 dr->depth);
1081 dr->depth);
1082 /* save to disk */ 1073 /* save to disk */
1083 if ((GNUNET_YES == prc->do_store) && 1074 if ((GNUNET_YES == prc->do_store) &&
1084 ((NULL != dc->filename) || (is_recursive_download (dc))) && 1075 ((NULL != dc->filename) || (is_recursive_download (dc))) &&
1085 ((dr->depth == dc->treedepth) || 1076 ((dr->depth == dc->treedepth) ||
1086 (0 == (dc->options & GNUNET_FS_DOWNLOAD_NO_TEMPORARIES)))) 1077 (0 == (dc->options & GNUNET_FS_DOWNLOAD_NO_TEMPORARIES))))
1087 { 1078 {
1088 fh = GNUNET_DISK_file_open (NULL != dc->filename 1079 fh = GNUNET_DISK_file_open (NULL != dc->filename ? dc->filename
1089 ? dc->filename : dc->temp_filename, 1080 : dc->temp_filename,
1090 GNUNET_DISK_OPEN_READWRITE | 1081 GNUNET_DISK_OPEN_READWRITE |
1091 GNUNET_DISK_OPEN_CREATE, 1082 GNUNET_DISK_OPEN_CREATE,
1092 GNUNET_DISK_PERM_USER_READ | 1083 GNUNET_DISK_PERM_USER_READ |
1093 GNUNET_DISK_PERM_USER_WRITE | 1084 GNUNET_DISK_PERM_USER_WRITE |
1094 GNUNET_DISK_PERM_GROUP_READ | 1085 GNUNET_DISK_PERM_GROUP_READ |
1095 GNUNET_DISK_PERM_OTHER_READ); 1086 GNUNET_DISK_PERM_OTHER_READ);
1096 if (NULL == fh) 1087 if (NULL == fh)
1097 { 1088 {
1098 GNUNET_asprintf (&dc->emsg, 1089 GNUNET_asprintf (&dc->emsg,
1099 _("Download failed: could not open file `%s': %s"), 1090 _ ("Download failed: could not open file `%s': %s"),
1100 dc->filename, STRERROR (errno)); 1091 dc->filename,
1092 strerror (errno));
1101 goto signal_error; 1093 goto signal_error;
1102 } 1094 }
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Saving decrypted block to disk at offset %llu\n", 1096 "Saving decrypted block to disk at offset %llu\n",
1105 (unsigned long long) off); 1097 (unsigned long long) off);
1106 if ((off != GNUNET_DISK_file_seek (fh, 1098 if ((off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET)))
1107 off,
1108 GNUNET_DISK_SEEK_SET)))
1109 { 1099 {
1110 GNUNET_asprintf (&dc->emsg, 1100 GNUNET_asprintf (&dc->emsg,
1111 _("Failed to seek to offset %llu in file `%s': %s"), 1101 _ ("Failed to seek to offset %llu in file `%s': %s"),
1112 (unsigned long long) off, 1102 (unsigned long long) off,
1113 dc->filename, 1103 dc->filename,
1114 STRERROR (errno)); 1104 strerror (errno));
1115 goto signal_error; 1105 goto signal_error;
1116 } 1106 }
1117 if (prc->size != GNUNET_DISK_file_write (fh, pt, prc->size)) 1107 if (prc->size != GNUNET_DISK_file_write (fh, pt, prc->size))
1118 { 1108 {
1119 GNUNET_asprintf (&dc->emsg, 1109 GNUNET_asprintf (
1120 _("Failed to write block of %u bytes at offset %llu in file `%s': %s"), 1110 &dc->emsg,
1121 (unsigned int) prc->size, 1111 _ ("Failed to write block of %u bytes at offset %llu in file `%s': %s"),
1122 (unsigned long long) off, 1112 (unsigned int) prc->size,
1123 dc->filename, 1113 (unsigned long long) off,
1124 STRERROR (errno)); 1114 dc->filename,
1115 strerror (errno));
1125 goto signal_error; 1116 goto signal_error;
1126 } 1117 }
1127 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); 1118 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
@@ -1153,8 +1144,11 @@ process_result_with_request (void *cls,
1153 * says it is a directory or if no meta data is given AND filename 1144 * says it is a directory or if no meta data is given AND filename
1154 * ends in '.gnd' (top-level case) */ 1145 * ends in '.gnd' (top-level case) */
1155 if (is_recursive_download (dc)) 1146 if (is_recursive_download (dc))
1156 GNUNET_FS_directory_list_contents (prc->size, pt, off, 1147 GNUNET_FS_directory_list_contents (prc->size,
1157 &trigger_recursive_download, dc); 1148 pt,
1149 off,
1150 &trigger_recursive_download,
1151 dc);
1158 } 1152 }
1159 GNUNET_assert (dc->completed <= dc->length); 1153 GNUNET_assert (dc->completed <= dc->length);
1160 dr->state = BRS_DOWNLOAD_DOWN; 1154 dr->state = BRS_DOWNLOAD_DOWN;
@@ -1164,13 +1158,15 @@ process_result_with_request (void *cls,
1164 pi.value.download.specifics.progress.data_len = prc->size; 1158 pi.value.download.specifics.progress.data_len = prc->size;
1165 pi.value.download.specifics.progress.depth = dr->depth; 1159 pi.value.download.specifics.progress.depth = dr->depth;
1166 pi.value.download.specifics.progress.respect_offered = prc->respect_offered; 1160 pi.value.download.specifics.progress.respect_offered = prc->respect_offered;
1167 pi.value.download.specifics.progress.num_transmissions = prc->num_transmissions; 1161 pi.value.download.specifics.progress.num_transmissions =
1168 if (prc->last_transmission.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 1162 prc->num_transmissions;
1169 pi.value.download.specifics.progress.block_download_duration 1163 if (prc->last_transmission.abs_value_us !=
1170 = GNUNET_TIME_absolute_get_duration (prc->last_transmission); 1164 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
1165 pi.value.download.specifics.progress.block_download_duration =
1166 GNUNET_TIME_absolute_get_duration (prc->last_transmission);
1171 else 1167 else
1172 pi.value.download.specifics.progress.block_download_duration 1168 pi.value.download.specifics.progress.block_download_duration =
1173 = GNUNET_TIME_UNIT_ZERO; /* found locally */ 1169 GNUNET_TIME_UNIT_ZERO; /* found locally */
1174 GNUNET_FS_download_make_status_ (&pi, dc); 1170 GNUNET_FS_download_make_status_ (&pi, dc);
1175 if (0 == dr->depth) 1171 if (0 == dr->depth)
1176 propagate_up (dr); 1172 propagate_up (dr);
@@ -1180,15 +1176,15 @@ process_result_with_request (void *cls,
1180 /* download completed, signal */ 1176 /* download completed, signal */
1181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1182 "Download completed, truncating file to desired length %llu\n", 1178 "Download completed, truncating file to desired length %llu\n",
1183 (unsigned long long) GNUNET_ntohll (dc->uri->data. 1179 (unsigned long long) GNUNET_ntohll (
1184 chk.file_length)); 1180 dc->uri->data.chk.file_length));
1185 /* truncate file to size (since we store IBlocks at the end) */ 1181 /* truncate file to size (since we store IBlocks at the end) */
1186 if (NULL != dc->filename) 1182 if (NULL != dc->filename)
1187 { 1183 {
1188 if (0 != 1184 if (0 != truncate (dc->filename,
1189 TRUNCATE (dc->filename, 1185 GNUNET_ntohll (dc->uri->data.chk.file_length)))
1190 GNUNET_ntohll (dc->uri->data.chk.file_length))) 1186 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1191 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", 1187 "truncate",
1192 dc->filename); 1188 dc->filename);
1193 } 1189 }
1194 GNUNET_assert (0 == dr->depth); 1190 GNUNET_assert (0 == dr->depth);
@@ -1201,9 +1197,11 @@ process_result_with_request (void *cls,
1201 return GNUNET_YES; 1197 return GNUNET_YES;
1202 } 1198 }
1203 1199
1204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1200 GNUNET_log (
1205 "Triggering downloads of children (this block was at depth %u and offset %llu)\n", 1201 GNUNET_ERROR_TYPE_DEBUG,
1206 dr->depth, (unsigned long long) dr->offset); 1202 "Triggering downloads of children (this block was at depth %u and offset %llu)\n",
1203 dr->depth,
1204 (unsigned long long) dr->offset);
1207 GNUNET_assert (0 == (prc->size % sizeof (struct ContentHashKey))); 1205 GNUNET_assert (0 == (prc->size % sizeof (struct ContentHashKey)));
1208 chkarr = (struct ContentHashKey *) pt; 1206 chkarr = (struct ContentHashKey *) pt;
1209 for (i = dr->num_children - 1; i >= 0; i--) 1207 for (i = dr->num_children - 1; i >= 0; i--)
@@ -1214,16 +1212,17 @@ process_result_with_request (void *cls,
1214 case BRS_INIT: 1212 case BRS_INIT:
1215 if ((drc->chk_idx + 1) * sizeof (struct ContentHashKey) > prc->size) 1213 if ((drc->chk_idx + 1) * sizeof (struct ContentHashKey) > prc->size)
1216 { 1214 {
1217 /* 'chkarr' does not have enough space for this chk_idx; 1215 /* 'chkarr' does not have enough space for this chk_idx;
1218 internal error! */ 1216 internal error! */
1219 GNUNET_break (0); GNUNET_assert (0); 1217 GNUNET_break (0);
1220 dc->emsg = GNUNET_strdup (_("internal error decoding tree")); 1218 GNUNET_assert (0);
1221 goto signal_error; 1219 dc->emsg = GNUNET_strdup (_ ("internal error decoding tree"));
1220 goto signal_error;
1222 } 1221 }
1223 drc->chk = chkarr[drc->chk_idx]; 1222 drc->chk = chkarr[drc->chk_idx];
1224 drc->state = BRS_CHK_SET; 1223 drc->state = BRS_CHK_SET;
1225 if (GNUNET_YES == dc->issue_requests) 1224 if (GNUNET_YES == dc->issue_requests)
1226 schedule_block_download (dc, drc); 1225 schedule_block_download (dc, drc);
1227 break; 1226 break;
1228 case BRS_RECONSTRUCT_DOWN: 1227 case BRS_RECONSTRUCT_DOWN:
1229 GNUNET_assert (0); 1228 GNUNET_assert (0);
@@ -1282,8 +1281,7 @@ signal_error:
1282 * @param msg message received 1281 * @param msg message received
1283 */ 1282 */
1284static int 1283static int
1285check_put (void *cls, 1284check_put (void *cls, const struct ClientPutMessage *cm)
1286 const struct ClientPutMessage *cm)
1287{ 1285{
1288 /* any varsize length is OK */ 1286 /* any varsize length is OK */
1289 return GNUNET_OK; 1287 return GNUNET_OK;
@@ -1298,8 +1296,7 @@ check_put (void *cls,
1298 * @param msg message received 1296 * @param msg message received
1299 */ 1297 */
1300static void 1298static void
1301handle_put (void *cls, 1299handle_put (void *cls, const struct ClientPutMessage *cm)
1302 const struct ClientPutMessage *cm)
1303{ 1300{
1304 struct GNUNET_FS_DownloadContext *dc = cls; 1301 struct GNUNET_FS_DownloadContext *dc = cls;
1305 uint16_t msize = ntohs (cm->header.size) - sizeof (*cm); 1302 uint16_t msize = ntohs (cm->header.size) - sizeof (*cm);
@@ -1313,9 +1310,7 @@ handle_put (void *cls,
1313 prc.do_store = GNUNET_YES; 1310 prc.do_store = GNUNET_YES;
1314 prc.respect_offered = ntohl (cm->respect_offered); 1311 prc.respect_offered = ntohl (cm->respect_offered);
1315 prc.num_transmissions = ntohl (cm->num_transmissions); 1312 prc.num_transmissions = ntohl (cm->num_transmissions);
1316 GNUNET_CRYPTO_hash (prc.data, 1313 GNUNET_CRYPTO_hash (prc.data, msize, &prc.query);
1317 msize,
1318 &prc.query);
1319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1320 "Received result for query `%s' from FS service\n", 1315 "Received result for query `%s' from FS service\n",
1321 GNUNET_h2s (&prc.query)); 1316 GNUNET_h2s (&prc.query));
@@ -1335,8 +1330,7 @@ handle_put (void *cls,
1335 * @param error error code 1330 * @param error error code
1336 */ 1331 */
1337static void 1332static void
1338download_mq_error_handler (void *cls, 1333download_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
1339 enum GNUNET_MQ_Error error)
1340{ 1334{
1341 struct GNUNET_FS_DownloadContext *dc = cls; 1335 struct GNUNET_FS_DownloadContext *dc = cls;
1342 1336
@@ -1360,13 +1354,12 @@ static void
1360do_reconnect (void *cls) 1354do_reconnect (void *cls)
1361{ 1355{
1362 struct GNUNET_FS_DownloadContext *dc = cls; 1356 struct GNUNET_FS_DownloadContext *dc = cls;
1363 struct GNUNET_MQ_MessageHandler handlers[] = { 1357 struct GNUNET_MQ_MessageHandler handlers[] =
1364 GNUNET_MQ_hd_var_size (put, 1358 {GNUNET_MQ_hd_var_size (put,
1365 GNUNET_MESSAGE_TYPE_FS_PUT, 1359 GNUNET_MESSAGE_TYPE_FS_PUT,
1366 struct ClientPutMessage, 1360 struct ClientPutMessage,
1367 dc), 1361 dc),
1368 GNUNET_MQ_handler_end () 1362 GNUNET_MQ_handler_end ()};
1369 };
1370 1363
1371 dc->task = NULL; 1364 dc->task = NULL;
1372 dc->mq = GNUNET_CLIENT_connect (dc->h->cfg, 1365 dc->mq = GNUNET_CLIENT_connect (dc->h->cfg,
@@ -1377,13 +1370,12 @@ do_reconnect (void *cls)
1377 if (NULL == dc->mq) 1370 if (NULL == dc->mq)
1378 { 1371 {
1379 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1380 "Connecting to `%s'-service failed, will try again.\n", "FS"); 1373 "Connecting to `%s'-service failed, will try again.\n",
1374 "FS");
1381 try_reconnect (dc); 1375 try_reconnect (dc);
1382 return; 1376 return;
1383 } 1377 }
1384 GNUNET_CONTAINER_multihashmap_iterate (dc->active, 1378 GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc);
1385 &retry_entry,
1386 dc);
1387} 1379}
1388 1380
1389 1381
@@ -1411,13 +1403,11 @@ try_reconnect (struct GNUNET_FS_DownloadContext *dc)
1411 1403
1412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413 "Will try to reconnect in %s\n", 1405 "Will try to reconnect in %s\n",
1414 GNUNET_STRINGS_relative_time_to_string (dc->reconnect_backoff, 1406 GNUNET_STRINGS_relative_time_to_string (dc->reconnect_backoff,
1415 GNUNET_YES)); 1407 GNUNET_YES));
1416 GNUNET_break (NULL != dc->job_queue); 1408 GNUNET_break (NULL != dc->job_queue);
1417 dc->task = 1409 dc->task =
1418 GNUNET_SCHEDULER_add_delayed (dc->reconnect_backoff, 1410 GNUNET_SCHEDULER_add_delayed (dc->reconnect_backoff, &do_reconnect, dc);
1419 &do_reconnect,
1420 dc);
1421} 1411}
1422 1412
1423 1413
@@ -1437,11 +1427,9 @@ activate_fs_download (void *cls)
1437 GNUNET_assert (NULL != dc->active); 1427 GNUNET_assert (NULL != dc->active);
1438 do_reconnect (dc); 1428 do_reconnect (dc);
1439 if (NULL != dc->mq) 1429 if (NULL != dc->mq)
1440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download activated\n");
1441 "Download activated\n");
1442 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; 1431 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE;
1443 GNUNET_FS_download_make_status_ (&pi, 1432 GNUNET_FS_download_make_status_ (&pi, dc);
1444 dc);
1445} 1433}
1446 1434
1447 1435
@@ -1456,16 +1444,14 @@ deactivate_fs_download (void *cls)
1456 struct GNUNET_FS_DownloadContext *dc = cls; 1444 struct GNUNET_FS_DownloadContext *dc = cls;
1457 struct GNUNET_FS_ProgressInfo pi; 1445 struct GNUNET_FS_ProgressInfo pi;
1458 1446
1459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download deactivated\n");
1460 "Download deactivated\n");
1461 if (NULL != dc->mq) 1448 if (NULL != dc->mq)
1462 { 1449 {
1463 GNUNET_MQ_destroy (dc->mq); 1450 GNUNET_MQ_destroy (dc->mq);
1464 dc->mq = NULL; 1451 dc->mq = NULL;
1465 } 1452 }
1466 pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE; 1453 pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE;
1467 GNUNET_FS_download_make_status_ (&pi, 1454 GNUNET_FS_download_make_status_ (&pi, dc);
1468 dc);
1469} 1455}
1470 1456
1471 1457
@@ -1490,8 +1476,8 @@ deactivate_fs_download (void *cls)
1490 */ 1476 */
1491static struct DownloadRequest * 1477static struct DownloadRequest *
1492create_download_request (struct DownloadRequest *parent, 1478create_download_request (struct DownloadRequest *parent,
1493 unsigned int chk_idx, 1479 unsigned int chk_idx,
1494 unsigned int depth, 1480 unsigned int depth,
1495 uint64_t dr_offset, 1481 uint64_t dr_offset,
1496 uint64_t file_start_offset, 1482 uint64_t file_start_offset,
1497 uint64_t desired_length) 1483 uint64_t desired_length)
@@ -1523,36 +1509,35 @@ create_download_request (struct DownloadRequest *parent,
1523 } 1509 }
1524 1510
1525 /* calculate index of last block at this level that is interesting (rounded up) */ 1511 /* calculate index of last block at this level that is interesting (rounded up) */
1526 dr->num_children = (file_start_offset + desired_length - dr_offset) / child_block_size; 1512 dr->num_children =
1513 (file_start_offset + desired_length - dr_offset) / child_block_size;
1527 if (dr->num_children * child_block_size < 1514 if (dr->num_children * child_block_size <
1528 file_start_offset + desired_length - dr_offset) 1515 file_start_offset + desired_length - dr_offset)
1529 dr->num_children++; /* round up */ 1516 dr->num_children++; /* round up */
1530 GNUNET_assert (dr->num_children > head_skip); 1517 GNUNET_assert (dr->num_children > head_skip);
1531 dr->num_children -= head_skip; 1518 dr->num_children -= head_skip;
1532 if (dr->num_children > CHK_PER_INODE) 1519 if (dr->num_children > CHK_PER_INODE)
1533 dr->num_children = CHK_PER_INODE; /* cap at max */ 1520 dr->num_children = CHK_PER_INODE; /* cap at max */
1534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1535 "Block at offset %llu and depth %u has %u children\n", 1522 "Block at offset %llu and depth %u has %u children\n",
1536 (unsigned long long) dr_offset, 1523 (unsigned long long) dr_offset,
1537 depth, 1524 depth,
1538 dr->num_children); 1525 dr->num_children);
1539 1526
1540 /* now we can get the total number of *interesting* children for this block */ 1527 /* now we can get the total number of *interesting* children for this block */
1541 1528
1542 /* why else would we have gotten here to begin with? (that'd be a bad logic error) */ 1529 /* why else would we have gotten here to begin with? (that'd be a bad logic error) */
1543 GNUNET_assert (dr->num_children > 0); 1530 GNUNET_assert (dr->num_children > 0);
1544 1531
1545 dr->children = 1532 dr->children = GNUNET_new_array (dr->num_children, struct DownloadRequest *);
1546 GNUNET_new_array (dr->num_children,
1547 struct DownloadRequest *);
1548 for (i = 0; i < dr->num_children; i++) 1533 for (i = 0; i < dr->num_children; i++)
1549 { 1534 {
1550 dr->children[i] = 1535 dr->children[i] =
1551 create_download_request (dr, 1536 create_download_request (dr,
1552 i + head_skip, 1537 i + head_skip,
1553 depth - 1, 1538 depth - 1,
1554 dr_offset + (i + head_skip) * child_block_size, 1539 dr_offset + (i + head_skip) * child_block_size,
1555 file_start_offset, 1540 file_start_offset,
1556 desired_length); 1541 desired_length);
1557 } 1542 }
1558 return dr; 1543 return dr;
@@ -1583,8 +1568,7 @@ reconstruct_cont (void *cls)
1583 } 1568 }
1584 /* start "normal" download */ 1569 /* start "normal" download */
1585 dc->issue_requests = GNUNET_YES; 1570 dc->issue_requests = GNUNET_YES;
1586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1571 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting normal download\n");
1587 "Starting normal download\n");
1588 schedule_block_download (dc, dc->top_request); 1572 schedule_block_download (dc, dc->top_request);
1589} 1573}
1590 1574
@@ -1646,29 +1630,29 @@ reconstruct_cb (void *cls,
1646 if (chld < dr->children[0]->chk_idx) 1630 if (chld < dr->children[0]->chk_idx)
1647 { 1631 {
1648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1649 "Block %u < %u irrelevant for our range\n", 1633 "Block %u < %u irrelevant for our range\n",
1650 chld, 1634 chld,
1651 dr->children[0]->chk_idx); 1635 dr->children[0]->chk_idx);
1652 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, 1636 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc);
1653 dc);
1654 return; /* irrelevant block */ 1637 return; /* irrelevant block */
1655 } 1638 }
1656 if (chld > dr->children[dr->num_children-1]->chk_idx) 1639 if (chld > dr->children[dr->num_children - 1]->chk_idx)
1657 { 1640 {
1658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1659 "Block %u > %u irrelevant for our range\n", 1642 "Block %u > %u irrelevant for our range\n",
1660 chld, 1643 chld,
1661 dr->children[dr->num_children-1]->chk_idx); 1644 dr->children[dr->num_children - 1]->chk_idx);
1662 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); 1645 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc);
1663 return; /* irrelevant block */ 1646 return; /* irrelevant block */
1664 } 1647 }
1665 dr = dr->children[chld - dr->children[0]->chk_idx]; 1648 dr = dr->children[chld - dr->children[0]->chk_idx];
1666 } 1649 }
1667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1650 GNUNET_log (
1668 "Matched TE block with request at offset %llu and depth %u in state %d\n", 1651 GNUNET_ERROR_TYPE_DEBUG,
1669 (unsigned long long) dr->offset, 1652 "Matched TE block with request at offset %llu and depth %u in state %d\n",
1670 dr->depth, 1653 (unsigned long long) dr->offset,
1671 dr->state); 1654 dr->depth,
1655 dr->state);
1672 /* FIXME: this code needs more testing and might 1656 /* FIXME: this code needs more testing and might
1673 need to handle more states... */ 1657 need to handle more states... */
1674 switch (dr->state) 1658 switch (dr->state)
@@ -1684,10 +1668,11 @@ reconstruct_cb (void *cls,
1684 case BRS_CHK_SET: 1668 case BRS_CHK_SET:
1685 if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey))) 1669 if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey)))
1686 { 1670 {
1687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1671 GNUNET_log (
1688 "Reconstruction succeeded, can use block at offset %llu, depth %u\n", 1672 GNUNET_ERROR_TYPE_DEBUG,
1689 (unsigned long long) offset, 1673 "Reconstruction succeeded, can use block at offset %llu, depth %u\n",
1690 depth); 1674 (unsigned long long) offset,
1675 depth);
1691 /* block matches, hence tree below matches; 1676 /* block matches, hence tree below matches;
1692 * this request is done! */ 1677 * this request is done! */
1693 dr->state = BRS_DOWNLOAD_UP; 1678 dr->state = BRS_DOWNLOAD_UP;
@@ -1707,32 +1692,34 @@ reconstruct_cb (void *cls,
1707 pi.value.download.specifics.progress.data_len = 0; 1692 pi.value.download.specifics.progress.data_len = 0;
1708 pi.value.download.specifics.progress.depth = 0; 1693 pi.value.download.specifics.progress.depth = 0;
1709 pi.value.download.specifics.progress.respect_offered = 0; 1694 pi.value.download.specifics.progress.respect_offered = 0;
1710 pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; 1695 pi.value.download.specifics.progress.block_download_duration =
1696 GNUNET_TIME_UNIT_ZERO;
1711 GNUNET_FS_download_make_status_ (&pi, dc); 1697 GNUNET_FS_download_make_status_ (&pi, dc);
1712 /* FIXME: duplicated code from 'process_result_with_request - refactor */ 1698 /* FIXME: duplicated code from 'process_result_with_request - refactor */
1713 if (dc->completed == dc->length) 1699 if (dc->completed == dc->length)
1714 { 1700 {
1715 /* download completed, signal */ 1701 /* download completed, signal */
1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1717 "Download completed, truncating file to desired length %llu\n", 1703 "Download completed, truncating file to desired length %llu\n",
1718 (unsigned long long) GNUNET_ntohll (dc->uri->data. 1704 (unsigned long long) GNUNET_ntohll (
1719 chk.file_length)); 1705 dc->uri->data.chk.file_length));
1720 /* truncate file to size (since we store IBlocks at the end) */ 1706 /* truncate file to size (since we store IBlocks at the end) */
1721 if (NULL != dc->filename) 1707 if (NULL != dc->filename)
1722 { 1708 {
1723 if (0 != 1709 if (0 != truncate (dc->filename,
1724 TRUNCATE (dc->filename, 1710 GNUNET_ntohll (dc->uri->data.chk.file_length)))
1725 GNUNET_ntohll (dc->uri->data.chk.file_length))) 1711 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1726 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", 1712 "truncate",
1727 dc->filename); 1713 dc->filename);
1728 } 1714 }
1729 } 1715 }
1730 } 1716 }
1731 else 1717 else
1732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1718 GNUNET_log (
1733 "Reconstruction failed, need to download block at offset %llu, depth %u\n", 1719 GNUNET_ERROR_TYPE_DEBUG,
1734 (unsigned long long) offset, 1720 "Reconstruction failed, need to download block at offset %llu, depth %u\n",
1735 depth); 1721 (unsigned long long) offset,
1722 depth);
1736 break; 1723 break;
1737 case BRS_DOWNLOAD_DOWN: 1724 case BRS_DOWNLOAD_DOWN:
1738 break; 1725 break;
@@ -1744,10 +1731,8 @@ reconstruct_cb (void *cls,
1744 GNUNET_assert (0); 1731 GNUNET_assert (0);
1745 break; 1732 break;
1746 } 1733 }
1747 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, 1734 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc);
1748 dc); 1735 if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP))
1749 if ( (dr == dc->top_request) &&
1750 (dr->state == BRS_DOWNLOAD_UP) )
1751 check_completed (dc); 1736 check_completed (dc);
1752} 1737}
1753 1738
@@ -1803,8 +1788,7 @@ GNUNET_FS_download_start_task_ (void *cls)
1803 struct GNUNET_FS_ProgressInfo pi; 1788 struct GNUNET_FS_ProgressInfo pi;
1804 struct GNUNET_DISK_FileHandle *fh; 1789 struct GNUNET_DISK_FileHandle *fh;
1805 1790
1806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start task running...\n");
1807 "Start task running...\n");
1808 dc->task = NULL; 1792 dc->task = NULL;
1809 if (0 == dc->length) 1793 if (0 == dc->length)
1810 { 1794 {
@@ -1813,14 +1797,15 @@ GNUNET_FS_download_start_task_ (void *cls)
1813 { 1797 {
1814 fh = GNUNET_DISK_file_open (dc->filename, 1798 fh = GNUNET_DISK_file_open (dc->filename,
1815 GNUNET_DISK_OPEN_READWRITE | 1799 GNUNET_DISK_OPEN_READWRITE |
1816 GNUNET_DISK_OPEN_CREATE | 1800 GNUNET_DISK_OPEN_CREATE |
1817 ((0 == 1801 ((0 ==
1818 GNUNET_FS_uri_chk_get_file_size (dc->uri)) ? 1802 GNUNET_FS_uri_chk_get_file_size (dc->uri))
1819 GNUNET_DISK_OPEN_TRUNCATE : 0), 1803 ? GNUNET_DISK_OPEN_TRUNCATE
1804 : 0),
1820 GNUNET_DISK_PERM_USER_READ | 1805 GNUNET_DISK_PERM_USER_READ |
1821 GNUNET_DISK_PERM_USER_WRITE | 1806 GNUNET_DISK_PERM_USER_WRITE |
1822 GNUNET_DISK_PERM_GROUP_READ | 1807 GNUNET_DISK_PERM_GROUP_READ |
1823 GNUNET_DISK_PERM_OTHER_READ); 1808 GNUNET_DISK_PERM_OTHER_READ);
1824 GNUNET_DISK_file_close (fh); 1809 GNUNET_DISK_file_close (fh);
1825 } 1810 }
1826 GNUNET_FS_download_sync_ (dc); 1811 GNUNET_FS_download_sync_ (dc);
@@ -1834,13 +1819,16 @@ GNUNET_FS_download_start_task_ (void *cls)
1834 return; 1819 return;
1835 if (NULL == dc->top_request) 1820 if (NULL == dc->top_request)
1836 { 1821 {
1837 dc->top_request = 1822 dc->top_request = create_download_request (NULL,
1838 create_download_request (NULL, 0, dc->treedepth - 1, 0, dc->offset, 1823 0,
1839 dc->length); 1824 dc->treedepth - 1,
1825 0,
1826 dc->offset,
1827 dc->length);
1840 dc->top_request->state = BRS_CHK_SET; 1828 dc->top_request->state = BRS_CHK_SET;
1841 dc->top_request->chk = 1829 dc->top_request->chk = (dc->uri->type == GNUNET_FS_URI_CHK)
1842 (dc->uri->type == 1830 ? dc->uri->data.chk.chk
1843 GNUNET_FS_URI_CHK) ? dc->uri->data.chk.chk : dc->uri->data.loc.fi.chk; 1831 : dc->uri->data.loc.fi.chk;
1844 /* signal start */ 1832 /* signal start */
1845 GNUNET_FS_download_sync_ (dc); 1833 GNUNET_FS_download_sync_ (dc);
1846 if (NULL != dc->search) 1834 if (NULL != dc->search)
@@ -1852,23 +1840,24 @@ GNUNET_FS_download_start_task_ (void *cls)
1852 GNUNET_FS_download_start_downloading_ (dc); 1840 GNUNET_FS_download_start_downloading_ (dc);
1853 /* attempt reconstruction from disk */ 1841 /* attempt reconstruction from disk */
1854 if (GNUNET_YES == GNUNET_DISK_file_test (dc->filename)) 1842 if (GNUNET_YES == GNUNET_DISK_file_test (dc->filename))
1855 dc->rfh = 1843 dc->rfh = GNUNET_DISK_file_open (dc->filename,
1856 GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READ, 1844 GNUNET_DISK_OPEN_READ,
1857 GNUNET_DISK_PERM_NONE); 1845 GNUNET_DISK_PERM_NONE);
1858 if (dc->top_request->state == BRS_CHK_SET) 1846 if (dc->top_request->state == BRS_CHK_SET)
1859 { 1847 {
1860 if (NULL != dc->rfh) 1848 if (NULL != dc->rfh)
1861 { 1849 {
1862 /* first, try top-down */ 1850 /* first, try top-down */
1863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1864 "Trying top-down reconstruction for `%s'\n", dc->filename); 1852 "Trying top-down reconstruction for `%s'\n",
1853 dc->filename);
1865 try_top_down_reconstruction (dc, dc->top_request); 1854 try_top_down_reconstruction (dc, dc->top_request);
1866 switch (dc->top_request->state) 1855 switch (dc->top_request->state)
1867 { 1856 {
1868 case BRS_CHK_SET: 1857 case BRS_CHK_SET:
1869 break; /* normal */ 1858 break; /* normal */
1870 case BRS_DOWNLOAD_DOWN: 1859 case BRS_DOWNLOAD_DOWN:
1871 break; /* normal, some blocks already down */ 1860 break; /* normal, some blocks already down */
1872 case BRS_DOWNLOAD_UP: 1861 case BRS_DOWNLOAD_UP:
1873 /* already done entirely, party! */ 1862 /* already done entirely, party! */
1874 if (NULL != dc->rfh) 1863 if (NULL != dc->rfh)
@@ -1880,7 +1869,7 @@ GNUNET_FS_download_start_task_ (void *cls)
1880 } 1869 }
1881 return; 1870 return;
1882 case BRS_ERROR: 1871 case BRS_ERROR:
1883 GNUNET_asprintf (&dc->emsg, _("Invalid URI")); 1872 GNUNET_asprintf (&dc->emsg, _ ("Invalid URI"));
1884 GNUNET_FS_download_sync_ (dc); 1873 GNUNET_FS_download_sync_ (dc);
1885 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; 1874 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR;
1886 pi.value.download.specifics.error.message = dc->emsg; 1875 pi.value.download.specifics.error.message = dc->emsg;
@@ -1896,11 +1885,11 @@ GNUNET_FS_download_start_task_ (void *cls)
1896 if ((GNUNET_FS_uri_chk_get_file_size (dc->uri) <= MAX_INLINE_SIZE) && 1885 if ((GNUNET_FS_uri_chk_get_file_size (dc->uri) <= MAX_INLINE_SIZE) &&
1897 (NULL != dc->meta)) 1886 (NULL != dc->meta))
1898 { 1887 {
1899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1888 GNUNET_log (
1900 "Trying to find embedded meta data for download of size %llu with %u bytes MD\n", 1889 GNUNET_ERROR_TYPE_DEBUG,
1901 (unsigned long long) GNUNET_FS_uri_chk_get_file_size (dc->uri), 1890 "Trying to find embedded meta data for download of size %llu with %u bytes MD\n",
1902 (unsigned int) 1891 (unsigned long long) GNUNET_FS_uri_chk_get_file_size (dc->uri),
1903 GNUNET_CONTAINER_meta_data_get_serialized_size (dc->meta)); 1892 (unsigned int) GNUNET_CONTAINER_meta_data_get_serialized_size (dc->meta));
1904 GNUNET_CONTAINER_meta_data_iterate (dc->meta, &match_full_data, dc); 1893 GNUNET_CONTAINER_meta_data_iterate (dc->meta, &match_full_data, dc);
1905 if (BRS_DOWNLOAD_UP == dc->top_request->state) 1894 if (BRS_DOWNLOAD_UP == dc->top_request->state)
1906 { 1895 {
@@ -1911,24 +1900,24 @@ GNUNET_FS_download_start_task_ (void *cls)
1911 GNUNET_DISK_file_close (dc->rfh); 1900 GNUNET_DISK_file_close (dc->rfh);
1912 dc->rfh = NULL; 1901 dc->rfh = NULL;
1913 } 1902 }
1914 return; /* finished, status update was already done for us */ 1903 return; /* finished, status update was already done for us */
1915 } 1904 }
1916 } 1905 }
1917 if (NULL != dc->rfh) 1906 if (NULL != dc->rfh)
1918 { 1907 {
1919 /* finally, actually run bottom-up */ 1908 /* finally, actually run bottom-up */
1920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1921 "Trying bottom-up reconstruction of file `%s'\n", dc->filename); 1910 "Trying bottom-up reconstruction of file `%s'\n",
1911 dc->filename);
1922 dc->te = 1912 dc->te =
1923 GNUNET_FS_tree_encoder_create (dc->h, 1913 GNUNET_FS_tree_encoder_create (dc->h,
1924 GNUNET_FS_uri_chk_get_file_size (dc->uri), 1914 GNUNET_FS_uri_chk_get_file_size (dc->uri),
1925 dc, 1915 dc,
1926 &fh_reader, 1916 &fh_reader,
1927 &reconstruct_cb, 1917 &reconstruct_cb,
1928 NULL, 1918 NULL,
1929 &reconstruct_cont); 1919 &reconstruct_cont);
1930 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, 1920 dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc);
1931 dc);
1932 } 1921 }
1933 else 1922 else
1934 { 1923 {
@@ -1968,7 +1957,8 @@ GNUNET_FS_download_signal_suspend_ (void *cls)
1968 dc->job_queue = NULL; 1957 dc->job_queue = NULL;
1969 } 1958 }
1970 if (NULL != dc->parent) 1959 if (NULL != dc->parent)
1971 GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, dc->parent->child_tail, 1960 GNUNET_CONTAINER_DLL_remove (dc->parent->child_head,
1961 dc->parent->child_tail,
1972 dc); 1962 dc);
1973 if (NULL != dc->task) 1963 if (NULL != dc->task)
1974 { 1964 {
@@ -2024,14 +2014,14 @@ GNUNET_FS_download_signal_suspend_ (void *cls)
2024 */ 2014 */
2025struct GNUNET_FS_DownloadContext * 2015struct GNUNET_FS_DownloadContext *
2026create_download_context (struct GNUNET_FS_Handle *h, 2016create_download_context (struct GNUNET_FS_Handle *h,
2027 const struct GNUNET_FS_Uri *uri, 2017 const struct GNUNET_FS_Uri *uri,
2028 const struct GNUNET_CONTAINER_MetaData *meta, 2018 const struct GNUNET_CONTAINER_MetaData *meta,
2029 const char *filename, 2019 const char *filename,
2030 const char *tempname, 2020 const char *tempname,
2031 uint64_t offset, 2021 uint64_t offset,
2032 uint64_t length, 2022 uint64_t length,
2033 uint32_t anonymity, 2023 uint32_t anonymity,
2034 enum GNUNET_FS_DownloadOptions options, 2024 enum GNUNET_FS_DownloadOptions options,
2035 void *cctx) 2025 void *cctx)
2036{ 2026{
2037 struct GNUNET_FS_DownloadContext *dc; 2027 struct GNUNET_FS_DownloadContext *dc;
@@ -2045,10 +2035,10 @@ create_download_context (struct GNUNET_FS_Handle *h,
2045 } 2035 }
2046 dc = GNUNET_new (struct GNUNET_FS_DownloadContext); 2036 dc = GNUNET_new (struct GNUNET_FS_DownloadContext);
2047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2048 "Starting download %p, %u bytes at offset %llu\n", 2038 "Starting download %p, %u bytes at offset %llu\n",
2049 dc, 2039 dc,
2050 (unsigned int) length, 2040 (unsigned int) length,
2051 (unsigned long long) offset); 2041 (unsigned long long) offset);
2052 dc->h = h; 2042 dc->h = h;
2053 dc->uri = GNUNET_FS_uri_dup (uri); 2043 dc->uri = GNUNET_FS_uri_dup (uri);
2054 dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); 2044 dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
@@ -2058,7 +2048,10 @@ create_download_context (struct GNUNET_FS_Handle *h,
2058 { 2048 {
2059 dc->filename = GNUNET_strdup (filename); 2049 dc->filename = GNUNET_strdup (filename);
2060 if (GNUNET_YES == GNUNET_DISK_file_test (filename)) 2050 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
2061 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES)); 2051 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename,
2052 &dc->old_file_size,
2053 GNUNET_YES,
2054 GNUNET_YES));
2062 } 2055 }
2063 if (GNUNET_FS_uri_test_loc (dc->uri)) 2056 if (GNUNET_FS_uri_test_loc (dc->uri))
2064 GNUNET_assert (GNUNET_OK == 2057 GNUNET_assert (GNUNET_OK ==
@@ -2068,9 +2061,10 @@ create_download_context (struct GNUNET_FS_Handle *h,
2068 dc->anonymity = anonymity; 2061 dc->anonymity = anonymity;
2069 dc->options = options; 2062 dc->options = options;
2070 dc->active = 2063 dc->active =
2071 GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE), GNUNET_NO); 2064 GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE),
2065 GNUNET_NO);
2072 dc->treedepth = 2066 dc->treedepth =
2073 GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri)); 2067 GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri));
2074 if ((NULL == filename) && (is_recursive_download (dc))) 2068 if ((NULL == filename) && (is_recursive_download (dc)))
2075 { 2069 {
2076 if (NULL != tempname) 2070 if (NULL != tempname)
@@ -2079,13 +2073,12 @@ create_download_context (struct GNUNET_FS_Handle *h,
2079 dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp"); 2073 dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp");
2080 } 2074 }
2081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2082 "Starting download `%s' of %llu bytes with tree depth %u\n", 2076 "Starting download `%s' of %llu bytes with tree depth %u\n",
2083 filename, 2077 filename,
2084 (unsigned long long) length, 2078 (unsigned long long) length,
2085 dc->treedepth); 2079 dc->treedepth);
2086 GNUNET_assert (NULL == dc->job_queue); 2080 GNUNET_assert (NULL == dc->job_queue);
2087 dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, 2081 dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc);
2088 dc);
2089 return dc; 2082 return dc;
2090} 2083}
2091 2084
@@ -2140,7 +2133,7 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
2140 meta, 2133 meta,
2141 filename, 2134 filename,
2142 tempname, 2135 tempname,
2143 offset, 2136 offset,
2144 length, 2137 length,
2145 anonymity, 2138 anonymity,
2146 options, 2139 options,
@@ -2150,9 +2143,9 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
2150 dc->parent = parent; 2143 dc->parent = parent;
2151 if (NULL != parent) 2144 if (NULL != parent)
2152 GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc); 2145 GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc);
2153 else if (0 == (GNUNET_FS_DOWNLOAD_IS_PROBE & options) ) 2146 else if (0 == (GNUNET_FS_DOWNLOAD_IS_PROBE & options))
2154 dc->top = 2147 dc->top =
2155 GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc); 2148 GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc);
2156 return dc; 2149 return dc;
2157} 2150}
2158 2151
@@ -2214,7 +2207,7 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h,
2214 sr->meta, 2207 sr->meta,
2215 filename, 2208 filename,
2216 tempname, 2209 tempname,
2217 offset, 2210 offset,
2218 length, 2211 length,
2219 anonymity, 2212 anonymity,
2220 options, 2213 options,
@@ -2248,19 +2241,19 @@ GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc)
2248 GNUNET_assert (NULL == dc->job_queue); 2241 GNUNET_assert (NULL == dc->job_queue);
2249 GNUNET_assert (NULL == dc->task); 2242 GNUNET_assert (NULL == dc->task);
2250 GNUNET_assert (NULL != dc->active); 2243 GNUNET_assert (NULL != dc->active);
2251 dc->job_queue 2244 dc->job_queue =
2252 = GNUNET_FS_queue_ (dc->h, 2245 GNUNET_FS_queue_ (dc->h,
2253 &activate_fs_download, 2246 &activate_fs_download,
2254 &deactivate_fs_download, 2247 &deactivate_fs_download,
2255 dc, 2248 dc,
2256 (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE, 2249 (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE,
2257 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) 2250 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
2258 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL 2251 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL
2259 : GNUNET_FS_QUEUE_PRIORITY_PROBE); 2252 : GNUNET_FS_QUEUE_PRIORITY_PROBE);
2260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261 "Download %p put into queue as job %p\n", 2254 "Download %p put into queue as job %p\n",
2262 dc, 2255 dc,
2263 dc->job_queue); 2256 dc->job_queue);
2264} 2257}
2265 2258
2266/** 2259/**
@@ -2271,7 +2264,7 @@ GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc)
2271void 2264void
2272GNUNET_FS_download_suspend (struct GNUNET_FS_DownloadContext *dc) 2265GNUNET_FS_download_suspend (struct GNUNET_FS_DownloadContext *dc)
2273{ 2266{
2274 deactivate_fs_download(dc); 2267 deactivate_fs_download (dc);
2275} 2268}
2276 2269
2277 2270
@@ -2289,15 +2282,15 @@ GNUNET_FS_download_resume (struct GNUNET_FS_DownloadContext *dc)
2289 GNUNET_FS_download_make_status_ (&pi, dc); 2282 GNUNET_FS_download_make_status_ (&pi, dc);
2290 2283
2291 GNUNET_assert (NULL == dc->task); 2284 GNUNET_assert (NULL == dc->task);
2292 dc->job_queue 2285 dc->job_queue =
2293 = GNUNET_FS_queue_ (dc->h, 2286 GNUNET_FS_queue_ (dc->h,
2294 &activate_fs_download, 2287 &activate_fs_download,
2295 &deactivate_fs_download, 2288 &deactivate_fs_download,
2296 dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE, 2289 dc,
2297 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) 2290 (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE,
2291 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
2298 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL 2292 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL
2299 : GNUNET_FS_QUEUE_PRIORITY_PROBE); 2293 : GNUNET_FS_QUEUE_PRIORITY_PROBE);
2300
2301} 2294}
2302 2295
2303 2296
@@ -2308,8 +2301,7 @@ GNUNET_FS_download_resume (struct GNUNET_FS_DownloadContext *dc)
2308 * @param do_delete delete files of incomplete downloads 2301 * @param do_delete delete files of incomplete downloads
2309 */ 2302 */
2310void 2303void
2311GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, 2304GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete)
2312 int do_delete)
2313{ 2305{
2314 struct GNUNET_FS_ProgressInfo pi; 2306 struct GNUNET_FS_ProgressInfo pi;
2315 int have_children; 2307 int have_children;
@@ -2348,14 +2340,15 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc,
2348 dc); 2340 dc);
2349 if (NULL != dc->serialization) 2341 if (NULL != dc->serialization)
2350 GNUNET_FS_remove_sync_file_ (dc->h, 2342 GNUNET_FS_remove_sync_file_ (dc->h,
2351 ((NULL != dc->parent) || 2343 ((NULL != dc->parent) || (! search_was_null))
2352 (! search_was_null)) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : 2344 ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD
2353 GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, 2345 : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD,
2354 dc->serialization); 2346 dc->serialization);
2355 if ((GNUNET_YES == have_children) && (NULL == dc->parent)) 2347 if ((GNUNET_YES == have_children) && (NULL == dc->parent))
2356 GNUNET_FS_remove_sync_dir_ (dc->h, 2348 GNUNET_FS_remove_sync_dir_ (dc->h,
2357 (! search_was_null) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : 2349 (! search_was_null)
2358 GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, 2350 ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD
2351 : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD,
2359 dc->serialization); 2352 dc->serialization);
2360 pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; 2353 pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED;
2361 GNUNET_FS_download_make_status_ (&pi, dc); 2354 GNUNET_FS_download_make_status_ (&pi, dc);
@@ -2370,8 +2363,7 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc,
2370 { 2363 {
2371 if ((dc->completed != dc->length) && (GNUNET_YES == do_delete)) 2364 if ((dc->completed != dc->length) && (GNUNET_YES == do_delete))
2372 { 2365 {
2373 if ( (0 != UNLINK (dc->filename)) && 2366 if ((0 != unlink (dc->filename)) && (ENOENT != errno))
2374 (ENOENT != errno) )
2375 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 2367 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
2376 "unlink", 2368 "unlink",
2377 dc->filename); 2369 dc->filename);
@@ -2382,7 +2374,7 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc,
2382 GNUNET_FS_uri_destroy (dc->uri); 2374 GNUNET_FS_uri_destroy (dc->uri);
2383 if (NULL != dc->temp_filename) 2375 if (NULL != dc->temp_filename)
2384 { 2376 {
2385 if (0 != UNLINK (dc->temp_filename)) 2377 if (0 != unlink (dc->temp_filename))
2386 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 2378 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
2387 "unlink", 2379 "unlink",
2388 dc->temp_filename); 2380 dc->temp_filename);