Преглед изворни кода

fud: Implement file fetching and metadata/routing propagation.

parazyd пре 3 година
родитељ
комит
6cb9a47d4c
1 измењених фајлова са 48 додато и 8 уклоњено
  1. 48 8
      bin/fud/fud/src/main.rs

+ 48 - 8
bin/fud/fud/src/main.rs

@@ -52,7 +52,8 @@ use darkfi::{
 /// P2P protocols
 mod proto;
 use proto::{
-    FudChunkReply, FudChunkRequest, FudFilePut, FudFileReply, FudFileRequest, ProtocolFud,
+    FudChunkPut, FudChunkReply, FudChunkRequest, FudFilePut, FudFileReply, FudFileRequest,
+    ProtocolFud,
 };
 
 const CONFIG_FILE: &str = "fud_config.toml";
@@ -183,7 +184,36 @@ impl Fud {
 
         let chunked_file = match self.geode.get(&file_hash).await {
             Ok(v) => v,
-            Err(e) => todo!(), // fetch file
+            Err(Error::GeodeNeedsGc) => todo!(),
+            Err(Error::GeodeFileNotFound) => {
+                info!("Requested file {} not found in Geode, triggering fetch", file_hash);
+                self.file_fetch_tx.send((file_hash, Ok(()))).await.unwrap();
+                info!("Waiting for background file fetch task...");
+                let (i_file_hash, status) = self.file_fetch_rx.recv().await.unwrap();
+                match status {
+                    Ok(()) => {
+                        let ch_file = self.geode.get(&file_hash).await.unwrap();
+
+                        let m = FudFilePut {
+                            file_hash: i_file_hash,
+                            chunk_hashes: ch_file.iter().map(|(h, _)| *h).collect(),
+                        };
+
+                        self.p2p.broadcast(&m).await;
+
+                        ch_file
+                    }
+
+                    Err(Error::GeodeFileRouteNotFound) => {
+                        // TODO: Return FileNotFound error
+                        return JsonError::new(ErrorCode::InternalError, None, id).into()
+                    }
+
+                    Err(e) => panic!("{}", e),
+                }
+            }
+
+            Err(e) => panic!("{}", e),
         };
 
         if chunked_file.is_complete() {
@@ -205,16 +235,23 @@ impl Fud {
 
         for chunk in missing_chunks {
             self.chunk_fetch_tx.send((chunk, Ok(()))).await.unwrap();
-            let (_, result) = self.chunk_fetch_rx.recv().await.unwrap();
-            match result {
-                Ok(()) => continue,
-                Err(e) => todo!(),
+            let (i_chunk_hash, status) = self.chunk_fetch_rx.recv().await.unwrap();
+
+            match status {
+                Ok(()) => {
+                    let m = FudChunkPut { chunk_hash: i_chunk_hash };
+                    self.p2p.broadcast(&m).await;
+                    break
+                }
+                Err(Error::GeodeChunkRouteNotFound) => continue,
+
+                Err(e) => panic!("{}", e),
             }
         }
 
         let chunked_file = match self.geode.get(&file_hash).await {
             Ok(v) => v,
-            Err(e) => todo!(),
+            Err(e) => panic!("{}", e),
         };
 
         if !chunked_file.is_complete() {
@@ -481,7 +518,10 @@ async fn fetch_chunk_task(fud: Arc<Fud>, executor: Arc<Executor<'_>>) {
 
         if !found {
             warn!("Did not manage to fetch {} chunk", chunk_hash);
-            fud.chunk_fetch_tx.send((chunk_hash, Err(Error::GeodeChunkNotFound))).await.unwrap();
+            fud.chunk_fetch_tx
+                .send((chunk_hash, Err(Error::GeodeChunkRouteNotFound)))
+                .await
+                .unwrap();
             continue
         }