diff options
Diffstat (limited to 'src/rvi/parameters.rs')
-rw-r--r-- | src/rvi/parameters.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/rvi/parameters.rs b/src/rvi/parameters.rs new file mode 100644 index 0000000..1fa1a87 --- /dev/null +++ b/src/rvi/parameters.rs @@ -0,0 +1,136 @@ +use std::str; +use std::sync::Mutex; + +use datatype::{ChunkReceived, Event, DownloadComplete, UpdateRequestId, UpdateAvailable}; +use super::services::{BackendServices, RemoteServices}; +use super::transfers::Transfers; + + +/// Each `Parameter` implementation handles a specific kind of RVI client request, +/// optionally responding with an `Event` on completion. +pub trait Parameter { + fn handle(&self, remote: &Mutex<RemoteServices>, transfers: &Mutex<Transfers>) + -> Result<Option<Event>, String>; +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Notify { + update_available: UpdateAvailable, + services: BackendServices +} + +impl Parameter for Notify { + fn handle(&self, remote: &Mutex<RemoteServices>, _: &Mutex<Transfers>) -> Result<Option<Event>, String> { + remote.lock().unwrap().backend = Some(self.services.clone()); + Ok(Some(Event::NewUpdateAvailable(self.update_available.clone()))) + } +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Start { + update_id: UpdateRequestId, + chunkscount: u64, + checksum: String +} + +impl Parameter for Start { + fn handle(&self, remote: &Mutex<RemoteServices>, transfers: &Mutex<Transfers>) -> Result<Option<Event>, String> { + info!("Starting transfer for update_id {}", self.update_id); + let mut transfers = transfers.lock().unwrap(); + transfers.push(self.update_id.clone(), self.checksum.clone()); + + let remote = remote.lock().unwrap(); + let chunk = ChunkReceived { + device: remote.device_id.clone(), + update_id: self.update_id.clone(), + chunks: Vec::new() + }; + remote.send_chunk_received(chunk) + .map(|_| None) + .map_err(|err| format!("error sending start ack: {}", err)) + } +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Chunk { + update_id: UpdateRequestId, + bytes: String, + index: u64 +} + +impl Parameter for Chunk { + fn handle(&self, remote: &Mutex<RemoteServices>, transfers: &Mutex<Transfers>) -> Result<Option<Event>, String> { + let remote = remote.lock().unwrap(); + + let mut transfers = transfers.lock().unwrap(); + let transfer = try!(transfers.get_mut(self.update_id.clone()) + .ok_or(format!("couldn't find transfer for update_id {}", self.update_id))); + transfer.write_chunk(&self.bytes, self.index) + .map_err(|err| format!("couldn't write chunk: {}", err)) + .and_then(|_| { + trace!("wrote chunk {} for package {}", self.index, self.update_id); + let chunk = ChunkReceived { + device: remote.device_id.clone(), + update_id: self.update_id.clone(), + chunks: transfer.transferred_chunks.clone(), + }; + remote.send_chunk_received(chunk) + .map(|_| None) + .map_err(|err| format!("error sending ChunkReceived: {}", err)) + }) + } +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Finish { + update_id: UpdateRequestId, + signature: String +} + +impl Parameter for Finish { + fn handle(&self, _: &Mutex<RemoteServices>, transfers: &Mutex<Transfers>) -> Result<Option<Event>, String> { + let mut transfers = transfers.lock().unwrap(); + let image = { + let transfer = try!(transfers.get(self.update_id.clone()) + .ok_or(format!("unknown package: {}", self.update_id))); + let package = try!(transfer.assemble_package() + .map_err(|err| format!("couldn't assemble package: {}", err))); + try!(package.into_os_string().into_string() + .map_err(|err| format!("couldn't get image: {:?}", err))) + }; + transfers.remove(self.update_id.clone()); + info!("Finished transfer of {}", self.update_id); + + let complete = DownloadComplete { + update_id: self.update_id.clone(), + update_image: image, + signature: self.signature.clone() + }; + Ok(Some(Event::DownloadComplete(complete))) + } +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Report; + +impl Parameter for Report { + fn handle(&self, _: &Mutex<RemoteServices>, _: &Mutex<Transfers>) -> Result<Option<Event>, String> { + Ok(Some(Event::InstalledSoftwareNeeded)) + } +} + + +#[derive(RustcDecodable, RustcEncodable)] +pub struct Abort; + +impl Parameter for Abort { + fn handle(&self, _: &Mutex<RemoteServices>, transfers: &Mutex<Transfers>) -> Result<Option<Event>, String> { + transfers.lock().unwrap().clear(); + Ok(None) + } +} |