shutdown callback
[oweals/gnunet.git] / src / fs / fs_download.c
index 8d5a936f0a5a978eddb246350833e86ce1325e99..92c4b831d5b06b58990fa9d59a167645cacf91f9 100644 (file)
@@ -170,6 +170,7 @@ GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi,
     = GNUNET_TIME_calculate_eta (dc->start_time,
                                 dc->completed,
                                 dc->length);
+  pi->value.download.is_active = (dc->client == NULL) ? GNUNET_NO : GNUNET_YES;
   if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
     dc->client_info = dc->h->upcb (dc->h->upcb_cls,
                                   pi);
@@ -305,12 +306,10 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
                                     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,
@@ -332,15 +331,23 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
          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;
@@ -358,9 +365,11 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
            {
              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)
@@ -374,12 +383,18 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *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);
+    {
+#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);
+    }
 }
 
 
@@ -821,6 +836,24 @@ trigger_recursive_download (void *cls,
 }
 
 
+/**
+ * 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.
@@ -888,11 +921,16 @@ process_result_with_request (void *cls,
       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,
@@ -1076,7 +1114,10 @@ process_result_with_request (void *cls,
       dc->th = NULL;
     }
   GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
-  /* FIXME: clean up dc->active / pending! */
+  GNUNET_CONTAINER_multihashmap_iterate (dc->active,
+                                        &free_entry,
+                                        NULL);
+  dc->pending = NULL;
   dc->client = NULL;
   GNUNET_free (sm);
   GNUNET_FS_download_sync_ (dc);
@@ -1182,6 +1223,10 @@ transmit_download_request (void *cls,
   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;
     }
@@ -1305,6 +1350,10 @@ try_reconnect (struct GNUNET_FS_DownloadContext *dc)
   
   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);
@@ -1316,6 +1365,10 @@ try_reconnect (struct GNUNET_FS_DownloadContext *dc)
       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,
@@ -1339,6 +1392,8 @@ activate_fs_download (void *cls,
   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,
@@ -1349,14 +1404,12 @@ activate_fs_download (void *cls,
   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);    
 }
 
 
@@ -1386,24 +1439,6 @@ deactivate_fs_download (void *cls)
 }
 
 
-/**
- * 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;
-}
-
-
 /**
  * Create SUSPEND event for the given download operation
  * and then clean up our state (without stop signal).
@@ -1556,6 +1591,12 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
              "Download tree has depth %u\n",
              dc->treedepth);
 #endif
+  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);
@@ -1565,11 +1606,6 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h,
                           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,
-                                 &GNUNET_FS_download_signal_suspend_,
-                                 dc);
-
   return dc;
 }
 
@@ -1622,7 +1658,8 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h,
   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;
@@ -1706,6 +1743,7 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h,
 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,
@@ -1749,13 +1787,16 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc,
                                 dc);  
   if (dc->serialization != NULL)
     GNUNET_FS_remove_sync_file_ (dc->h,
-                                (dc->parent != NULL) 
-                                ? "subdownloads" 
-                                : "download"
+                                ( (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)
-    GNUNET_FS_remove_sync_dir_ (dc->h,                       
-                               "subdownloads",
+  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);