Skip to content

Commit

Permalink
Ask user before receiving files (Closes #1)
Browse files Browse the repository at this point in the history
  • Loading branch information
faulesocke committed Nov 10, 2020
1 parent 5388e77 commit 9aff641
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 30 deletions.
4 changes: 3 additions & 1 deletion examples/test-file-rust2rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ async fn receive(code_rx: mpsc::Receiver<String>) {

let mut w = connector.connect_to_client().await;
info!("Got key: {}", &w.key);
transfer::receive_file(
let req = transfer::request_file(
&mut w,
&magic_wormhole::transit::DEFAULT_RELAY_SERVER
.parse()
.unwrap(),
)
.await
.unwrap();

req.resolve().await.unwrap();
}

async fn send(code_tx: mpsc::Sender<String>) {
Expand Down
43 changes: 41 additions & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,46 @@ async fn send_many(
}

async fn receive(mut w: Wormhole, relay_server: &str) -> anyhow::Result<()> {
transfer::receive_file(&mut w, &relay_server.parse().unwrap()).await?;
use async_std::io;
use async_std::prelude::*;

Ok(())
let req = transfer::request_file(&mut w, &relay_server.parse().unwrap()).await?;

let mut stdout = io::stdout();
let stdin = io::stdin();

let answer = loop {
stdout
.write_fmt(format_args!(
"Receive file '{}' (size: {} bytes)? (y/N) ",
req.filename.display(),
req.filesize
))
.await
.unwrap();

stdout.flush().await.unwrap();

let mut answer = String::new();
stdin.read_line(&mut answer).await.unwrap();

match answer.chars().next() {
Some('y') | Some('Y') => break true,
Some('n') | Some('N') => break false,
_ => {
stdout
.write_fmt(format_args!("Please type y or n!\n"))
.await
.unwrap();
stdout.flush().await.unwrap();
continue;
},
};
};

if answer {
req.accept().await
} else {
req.reject().await
}
}
96 changes: 69 additions & 27 deletions src/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use sha2::{digest::FixedOutput, Digest, Sha256};
use sodiumoxide::crypto::secretbox;
use std::path::Path;
use std::path::PathBuf;
use transit::TransitConnector;
use transit::TransitType;

/// The App ID associated with this protocol.
pub const APPID: &str = "lothar.com/wormhole/text-or-file-xfer";
Expand Down Expand Up @@ -215,7 +217,10 @@ pub async fn send_file(
.context("Could not send file")
}

pub async fn receive_file(wormhole: &mut Wormhole, relay_url: &RelayUrl) -> Result<()> {
pub async fn request_file<'a>(
wormhole: &'a mut Wormhole,
relay_url: &RelayUrl,
) -> Result<ReceiveRequest<'a>> {
let connector = transit::init(transit::Ability::all_abilities(), relay_url).await?;

// send the transit message
Expand All @@ -230,16 +235,16 @@ pub async fn receive_file(wormhole: &mut Wormhole, relay_url: &RelayUrl) -> Resu
PeerMessage::Transit(transit) => {
debug!("received transit message: {:?}", transit);
transit
}
},
PeerMessage::Error(err) => {
anyhow::bail!("Something went wrong on the other side: {}", err);
}
},
other => {
anyhow::bail!(
"Got an unexpected message type, is the other side all right? Got: '{:?}'",
other
);
}
},
};

// 3. receive file offer message from peer
Expand All @@ -255,31 +260,68 @@ pub async fn receive_file(wormhole: &mut Wormhole, relay_url: &RelayUrl) -> Resu
_ => bail!("unexpected message: {:?}", maybe_offer),
};

// send file ack.
// TODO ask upper layer to ack the file.
debug!("Sending ack");
wormhole
.tx
.send(
PeerMessage::new_file_ack("ok")
.serialize()
.as_bytes()
.to_vec(),
)
.await?;
let req = ReceiveRequest {
wormhole,
filename,
filesize,
connector,
other_side_ttype,
};

let mut transit = connector
.receiver_connect(
wormhole.key.derive_transit_key(&wormhole.appid),
Arc::try_unwrap(other_side_ttype).unwrap(),
)
.await?;
Ok(req)
}

debug!("Beginning file transfer");
// TODO here's the right position for applying the output directory and to check for malicious (relative) file paths
tcp_file_receive(&mut transit, &filename, filesize)
.await
.context("Could not receive file")
#[must_use]
pub struct ReceiveRequest<'a> {
wormhole: &'a mut Wormhole,
connector: TransitConnector,
pub filename: PathBuf,
pub filesize: u64,
other_side_ttype: Arc<transit::TransitType>,
}

impl<'a> ReceiveRequest<'a> {
pub async fn accept(self) -> Result<()> {
// send file ack.
debug!("Sending ack");
self.wormhole
.tx
.send(
PeerMessage::new_file_ack("ok")
.serialize()
.as_bytes()
.to_vec(),
)
.await?;

let mut transit = self
.connector
.receiver_connect(
self.wormhole.key.derive_transit_key(&self.wormhole.appid),
Arc::try_unwrap(self.other_side_ttype).unwrap(),
)
.await?;

debug!("Beginning file transfer");
// TODO here's the right position for applying the output directory and to check for malicious (relative) file paths
tcp_file_receive(&mut transit, &self.filename, self.filesize)
.await
.context("Could not receive file")
}

pub async fn reject(self) -> Result<()> {
self.wormhole
.tx
.send(
PeerMessage::new_error_message("transfer rejected")
.serialize()
.as_bytes()
.to_vec(),
)
.await?;

Ok(())
}
}

// encrypt and send the file to tcp stream and return the sha256 sum
Expand Down

0 comments on commit 9aff641

Please sign in to comment.