* @author Christian Grothoff
*
* TODO:
- * - persistence (can wait)
* - location URI suppport (can wait, easy)
* - different priority for scheduling probe downloads?
* - check if iblocks can be computed from existing blocks (can wait, hard)
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
fh = NULL;
if ( (dc->old_file_size > off) &&
- (dc->filename != NULL) )
- {
- fh = GNUNET_DISK_file_open (dc->filename,
- GNUNET_DISK_OPEN_READ,
- GNUNET_DISK_PERM_NONE);
- }
+ (dc->filename != NULL) )
+ fh = GNUNET_DISK_file_open (dc->filename,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
if ( (fh != NULL) &&
(off ==
GNUNET_DISK_file_seek (fh,
GNUNET_HashCode query;
GNUNET_CRYPTO_hash_to_aes_key (&key, &sk, &iv);
- GNUNET_CRYPTO_aes_encrypt (block, len,
- &sk,
- &iv,
- enc);
+ if (-1 == GNUNET_CRYPTO_aes_encrypt (block, len,
+ &sk,
+ &iv,
+ enc))
+ {
+ GNUNET_break (0);
+ goto do_download;
+ }
GNUNET_CRYPTO_hash (enc, len, &query);
if (0 == memcmp (&query,
&chk->query,
sizeof (GNUNET_HashCode)))
{
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Matching block already present, no need for download!\n");
+#endif
/* already got it! */
prc.dc = dc;
prc.data = enc;
{
GNUNET_break_op (0);
}
+ GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
return;
}
}
+ do_download:
if (fh != NULL)
GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
if (depth < dc->treedepth)
if ( (dc->th == NULL) &&
(dc->client != NULL) )
- dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
- sizeof (struct SearchMessage),
- GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- GNUNET_NO,
- &transmit_download_request,
- dc);
+ {
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Asking for transmission to FS service\n");
+#endif
+ dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
+ sizeof (struct SearchMessage),
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ GNUNET_NO,
+ &transmit_download_request,
+ dc);
+ }
}
pos = pos->next;
}
dc->has_finished = GNUNET_YES;
+ GNUNET_FS_download_sync_ (dc);
/* signal completion */
pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED;
GNUNET_FS_download_make_status_ (&pi, dc);
}
+/**
+ * Free entries in the map.
+ *
+ * @param cls unused (NULL)
+ * @param key unused
+ * @param entry entry of type "struct DownloadRequest" which is freed
+ * @return GNUNET_OK
+ */
+static int
+free_entry (void *cls,
+ const GNUNET_HashCode *key,
+ void *entry)
+{
+ GNUNET_free (entry);
+ return GNUNET_OK;
+}
+
+
/**
* Iterator over entries in the pending requests in the 'active' map for the
* reply that we just got.
ppos = ppos->next;
}
GNUNET_CRYPTO_hash_to_aes_key (&sm->chk.key, &skey, &iv);
- GNUNET_CRYPTO_aes_decrypt (prc->data,
- prc->size,
- &skey,
- &iv,
- pt);
+ if (-1 == GNUNET_CRYPTO_aes_decrypt (prc->data,
+ prc->size,
+ &skey,
+ &iv,
+ pt))
+ {
+ GNUNET_break (0);
+ dc->emsg = GNUNET_strdup ("internal error decrypting content");
+ goto signal_error;
+ }
off = compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length),
sm->offset,
sm->depth,
}
GNUNET_assert (sm->depth == dc->treedepth);
}
- // FIXME: make persistent
if (sm->depth == dc->treedepth)
{
+ GNUNET_FS_download_sync_ (dc);
GNUNET_free (sm);
return GNUNET_YES;
}
sm->depth + 1);
}
GNUNET_free (sm);
+ GNUNET_FS_download_sync_ (dc);
return GNUNET_YES;
signal_error:
dc->th = NULL;
}
GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
+ GNUNET_CONTAINER_multihashmap_iterate (dc->active,
+ &free_entry,
+ NULL);
+ dc->pending = NULL;
dc->client = NULL;
GNUNET_free (sm);
+ GNUNET_FS_download_sync_ (dc);
return GNUNET_NO;
}
dc->th = NULL;
if (NULL == buf)
{
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmitting download request failed, trying to reconnect\n");
+#endif
try_reconnect (dc);
return 0;
}
if (NULL != dc->client)
{
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Moving all requests back to pending list\n");
+#endif
if (NULL != dc->th)
{
GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th);
GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
dc->client = NULL;
}
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Will try to reconnect in 1s\n");
+#endif
dc->task
= GNUNET_SCHEDULER_add_delayed (dc->h->sched,
GNUNET_TIME_UNIT_SECONDS,
struct GNUNET_FS_ProgressInfo pi;
GNUNET_assert (NULL != client);
+ GNUNET_assert (dc->client == NULL);
+ GNUNET_assert (dc->th == NULL);
dc->client = client;
GNUNET_CLIENT_receive (client,
&receive_results,
GNUNET_CONTAINER_multihashmap_iterate (dc->active,
&retry_entry,
dc);
- if ( (dc->th == NULL) &&
- (dc->client != NULL) )
- dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
- sizeof (struct SearchMessage),
- GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- GNUNET_NO,
- &transmit_download_request,
- dc);
+ dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
+ sizeof (struct SearchMessage),
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ GNUNET_NO,
+ &transmit_download_request,
+ dc);
}
* Create SUSPEND event for the given download operation
* and then clean up our state (without stop signal).
*
- * @param cls the 'struct GNUNET_FS_UnindexContext' to signal for
+ * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for
*/
-static void
-download_signal_suspend (void *cls)
+void
+GNUNET_FS_download_signal_suspend_ (void *cls)
{
struct GNUNET_FS_DownloadContext *dc = cls;
+ struct GNUNET_FS_ProgressInfo pi;
- GNUNET_FS_end_top (dc->h, dc->top);
- /* FIXME: signal! */
+ if (dc->top != NULL)
+ GNUNET_FS_end_top (dc->h, dc->top);
+ while (NULL != dc->child_head)
+ GNUNET_FS_download_signal_suspend_ (dc->child_head);
+ if (dc->search != NULL)
+ {
+ dc->search->download = NULL;
+ dc->search = NULL;
+ }
+ if (dc->job_queue != NULL)
+ {
+ GNUNET_FS_dequeue_ (dc->job_queue);
+ dc->job_queue = NULL;
+ }
+ if (dc->parent != NULL)
+ GNUNET_CONTAINER_DLL_remove (dc->parent->child_head,
+ dc->parent->child_tail,
+ dc);
+ pi.status = GNUNET_FS_STATUS_DOWNLOAD_SUSPEND;
+ GNUNET_FS_download_make_status_ (&pi, dc);
+ if (GNUNET_SCHEDULER_NO_TASK != dc->task)
+ GNUNET_SCHEDULER_cancel (dc->h->sched,
+ dc->task);
+ GNUNET_CONTAINER_multihashmap_iterate (dc->active,
+ &free_entry,
+ NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (dc->active);
+ GNUNET_free_non_null (dc->filename);
+ GNUNET_CONTAINER_meta_data_destroy (dc->meta);
+ GNUNET_FS_uri_destroy (dc->uri);
+ GNUNET_free_non_null (dc->temp_filename);
+ GNUNET_free_non_null (dc->serialization);
GNUNET_free (dc);
}
"Download tree has depth %u\n",
dc->treedepth);
#endif
- // FIXME: make persistent
+ if (parent == NULL)
+ {
+ dc->top = GNUNET_FS_make_top (dc->h,
+ &GNUNET_FS_download_signal_suspend_,
+ dc);
+ }
pi.status = GNUNET_FS_STATUS_DOWNLOAD_START;
pi.value.download.specifics.start.meta = meta;
GNUNET_FS_download_make_status_ (&pi, dc);
&dc->uri->data.chk.chk,
0,
1 /* 0 == CHK, 1 == top */);
+ GNUNET_FS_download_sync_ (dc);
GNUNET_FS_download_start_downloading_ (dc);
- if (parent == NULL)
- dc->top = GNUNET_FS_make_top (dc->h,
- &download_signal_suspend,
- dc);
-
return dc;
}
struct GNUNET_FS_ProgressInfo pi;
struct GNUNET_FS_DownloadContext *dc;
- if (sr->download != NULL)
+ if ( (sr == NULL) ||
+ (sr->download != NULL) )
{
GNUNET_break (0);
return NULL;
dc->h = h;
dc->search = sr;
sr->download = dc;
+ if (sr->probe_ctx != NULL)
+ {
+ GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
+ sr->probe_ctx = NULL;
+ }
dc->uri = GNUNET_FS_uri_dup (sr->uri);
dc->meta = GNUNET_CONTAINER_meta_data_duplicate (sr->meta);
dc->client_info = cctx;
"Download tree has depth %u\n",
dc->treedepth);
#endif
- // FIXME: make persistent
pi.status = GNUNET_FS_STATUS_DOWNLOAD_START;
pi.value.download.specifics.start.meta = dc->meta;
GNUNET_FS_download_make_status_ (&pi, dc);
&dc->uri->data.chk.chk,
0,
1 /* 0 == CHK, 1 == top */);
+ GNUNET_FS_download_sync_ (dc);
GNUNET_FS_download_start_downloading_ (dc);
return dc;
}
void
GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc)
{
+ GNUNET_assert (dc->job_queue == NULL);
dc->job_queue = GNUNET_FS_queue_ (dc->h,
&activate_fs_download,
&deactivate_fs_download,
}
-/**
- * Free entries in the map.
- *
- * @param cls unused (NULL)
- * @param key unused
- * @param entry entry of type "struct DownloadRequest" which is freed
- * @return GNUNET_OK
- */
-static int
-free_entry (void *cls,
- const GNUNET_HashCode *key,
- void *entry)
-{
- GNUNET_free (entry);
- return GNUNET_OK;
-}
-
-
/**
* Stop a download (aborts if download is incomplete).
*
int do_delete)
{
struct GNUNET_FS_ProgressInfo pi;
+ int have_children;
if (dc->top != NULL)
GNUNET_FS_end_top (dc->h, dc->top);
GNUNET_FS_dequeue_ (dc->job_queue);
dc->job_queue = NULL;
}
+ have_children = (NULL != dc->child_head) ? GNUNET_YES : GNUNET_NO;
while (NULL != dc->child_head)
GNUNET_FS_download_stop (dc->child_head,
do_delete);
- // FIXME: make unpersistent
if (dc->parent != NULL)
GNUNET_CONTAINER_DLL_remove (dc->parent->child_head,
dc->parent->child_tail,
- dc);
-
+ dc);
+ if (dc->serialization != NULL)
+ GNUNET_FS_remove_sync_file_ (dc->h,
+ ( (dc->parent != NULL) || (dc->search != NULL) )
+ ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD
+ : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD ,
+ dc->serialization);
+ if ( (GNUNET_YES == have_children) &&
+ (dc->parent == NULL) )
+ GNUNET_FS_remove_sync_dir_ (dc->h,
+ (dc->search != NULL)
+ ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD
+ : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD,
+ dc->serialization);
pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED;
GNUNET_FS_download_make_status_ (&pi, dc);
if (GNUNET_SCHEDULER_NO_TASK != dc->task)
dc->temp_filename);
GNUNET_free (dc->temp_filename);
}
- /* FIXME: clean up serialization file itself! */
GNUNET_free_non_null (dc->serialization);
GNUNET_free (dc);
}