diff --git a/src/config.rs b/src/config.rs index 061635f2..763cfe70 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,11 +22,13 @@ pub const LAUNCHER_LOCAL_CONFIG_FILE_NAME: &'static str = ".launcher.config"; pub const LAUNCHER_GLOBAL_CONFIG_FILE_NAME: &'static str = "LauncherSpecificConfigurationFile"; pub const MAX_ALLOWED_READ_PAYLOAD_SIZE_BYTES: u64 = 300 * 1024 * 1024; -pub fn get_base64_config() -> ::rustc_serialize::base64::Config { - ::rustc_serialize::base64::Config { - char_set : ::rustc_serialize::base64::CharacterSet::Standard, - newline : ::rustc_serialize::base64::Newline::LF, - pad : true, +use rustc_serialize::base64::{CharacterSet, Config, Newline}; + +pub fn get_base64_config() -> Config { + Config { + char_set: CharacterSet::Standard, + newline: Newline::LF, + pad: true, line_length: None, } } diff --git a/src/errors.rs b/src/errors.rs index 1f60c303..b2b4a18f 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,31 +15,40 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::io; +use std::fmt; + +use rustc_serialize::json; + +use safe_core::errors::CoreError; +use safe_dns::errors::{DNS_ERROR_START_RANGE, DnsError}; +use safe_nfs::errors::NfsError; + use maidsafe_utilities::serialisation::SerialisationError; -/// Intended for converting Launcher Errors into numeric codes for propagating some error information -/// across FFI boundaries and specially to C. -pub const LAUNCHER_ERROR_START_RANGE: i32 = ::safe_dns::errors::DNS_ERROR_START_RANGE - 500; +/// Intended for converting Launcher Errors into numeric codes for propagating some error +/// information across FFI boundaries and specially to C. +pub const LAUNCHER_ERROR_START_RANGE: i32 = DNS_ERROR_START_RANGE - 500; /// Launcher Errors pub enum LauncherError { /// Error from safe_core. Boxed to hold a pointer instead of value so that this enum variant is /// not insanely bigger than others. - CoreError(Box<::safe_core::errors::CoreError>), + CoreError(Box), /// Errors from safe_nfs - NfsError(Box<::safe_nfs::errors::NfsError>), + NfsError(Box), /// Errors from safe_nfs - DnsError(Box<::safe_dns::errors::DnsError>), + DnsError(Box), /// Ipc Listener could not be bound to an endpoint IpcListenerCouldNotBeBound, /// The Ipc Listener has errored out. New apps will no longer be able to connect to Launcher - IpcListenerAborted(::std::io::Error), + IpcListenerAborted(io::Error), /// The Ipc Stream could not be cloned - IpcStreamCloneError(::std::io::Error), + IpcStreamCloneError(io::Error), /// mpsc receiver has hung up ReceiverChannelDisconnected, /// IpcSession has been terminated due to either graceful shutdown or some error as indicated - IpcSessionTerminated(Option<::std::io::Error>), + IpcSessionTerminated(Option), /// Could not read the payload size from stream FailedReadingStreamPayloadSize, /// Could not write the payload size to stream @@ -51,15 +60,15 @@ pub enum LauncherError { /// Permission denied - e.g. permission to access SAFEDrive etc. PermissionDenied, /// Could not parse payload as a valid JSON - JsonParseError(::rustc_serialize::json::ParserError), + JsonParseError(json::ParserError), /// Could not decode valid JSON into expected Structures probably because a mandatory field was /// missing or a field was wrongly named etc. - JsonDecodeError(::rustc_serialize::json::DecoderError), + JsonDecodeError(json::DecoderError), /// JSON non-conforming to the Launcher RFC and not covered by JsonDecodeError, e.g. things /// like invalid base64 formatting, unreasonable/unexpected indexing, ranges etc. SpecificParseError(String), /// Error encoding into Json String - JsonEncodeError(::rustc_serialize::json::EncoderError), + JsonEncodeError(json::EncoderError), /// Symmetric Deciphering failed for a cipher text SymmetricDecipherFailure, /// This path to binary has already been added on this machine @@ -67,7 +76,7 @@ pub enum LauncherError { /// The given app is not managed by Launcher AppNotRegistered, /// Starting of App as an external process has failed - AppActivationFailed(::std::io::Error), + AppActivationFailed(io::Error), /// Payload to read is prohibitive in size ReadPayloadSizeProhibitive, /// Unable to Read from or Write to a Local Config file. @@ -89,38 +98,38 @@ impl<'a> From<&'a str> for LauncherError { } } -impl From<::safe_core::errors::CoreError> for LauncherError { - fn from(error: ::safe_core::errors::CoreError) -> LauncherError { +impl From for LauncherError { + fn from(error: CoreError) -> LauncherError { LauncherError::CoreError(Box::new(error)) } } -impl From<::safe_nfs::errors::NfsError> for LauncherError { - fn from(error: ::safe_nfs::errors::NfsError) -> LauncherError { +impl From for LauncherError { + fn from(error: NfsError) -> LauncherError { LauncherError::NfsError(Box::new(error)) } } -impl From<::safe_dns::errors::DnsError> for LauncherError { - fn from(error: ::safe_dns::errors::DnsError) -> LauncherError { +impl From for LauncherError { + fn from(error: DnsError) -> LauncherError { LauncherError::DnsError(Box::new(error)) } } -impl From<::rustc_serialize::json::ParserError> for LauncherError { - fn from(error: ::rustc_serialize::json::ParserError) -> LauncherError { +impl From for LauncherError { + fn from(error: json::ParserError) -> LauncherError { LauncherError::JsonParseError(error) } } -impl From<::rustc_serialize::json::EncoderError> for LauncherError { - fn from(error: ::rustc_serialize::json::EncoderError) -> LauncherError { +impl From for LauncherError { + fn from(error: json::EncoderError) -> LauncherError { LauncherError::JsonEncodeError(error) } } -impl From<::rustc_serialize::json::DecoderError> for LauncherError { - fn from(error: ::rustc_serialize::json::DecoderError) -> LauncherError { +impl From for LauncherError { + fn from(error: json::DecoderError) -> LauncherError { LauncherError::JsonDecodeError(error) } } @@ -128,63 +137,103 @@ impl From<::rustc_serialize::json::DecoderError> for LauncherError { impl Into for LauncherError { fn into(self) -> i32 { match self { - LauncherError::CoreError(error) => (*error).into(), - LauncherError::NfsError(error) => (*error).into(), - LauncherError::DnsError(error) => (*error).into(), - LauncherError::IpcListenerCouldNotBeBound => LAUNCHER_ERROR_START_RANGE - 1, - LauncherError::IpcListenerAborted(_) => LAUNCHER_ERROR_START_RANGE - 2, - LauncherError::IpcStreamCloneError(_) => LAUNCHER_ERROR_START_RANGE - 3, - LauncherError::ReceiverChannelDisconnected => LAUNCHER_ERROR_START_RANGE - 4, - LauncherError::IpcSessionTerminated(_) => LAUNCHER_ERROR_START_RANGE - 5, - LauncherError::FailedReadingStreamPayloadSize => LAUNCHER_ERROR_START_RANGE - 6, - LauncherError::FailedWritingStreamPayloadSize => LAUNCHER_ERROR_START_RANGE - 7, - LauncherError::PathNotFound => LAUNCHER_ERROR_START_RANGE - 8, - LauncherError::InvalidPath => LAUNCHER_ERROR_START_RANGE - 9, - LauncherError::PermissionDenied => LAUNCHER_ERROR_START_RANGE - 10, - LauncherError::JsonParseError(_) => LAUNCHER_ERROR_START_RANGE - 11, - LauncherError::JsonDecodeError(_) => LAUNCHER_ERROR_START_RANGE - 12, - LauncherError::SpecificParseError(_) => LAUNCHER_ERROR_START_RANGE - 13, - LauncherError::JsonEncodeError(_) => LAUNCHER_ERROR_START_RANGE - 14, - LauncherError::SymmetricDecipherFailure => LAUNCHER_ERROR_START_RANGE - 15, - LauncherError::AppAlreadyAdded => LAUNCHER_ERROR_START_RANGE - 16, - LauncherError::AppNotRegistered => LAUNCHER_ERROR_START_RANGE - 17, - LauncherError::AppActivationFailed(_) => LAUNCHER_ERROR_START_RANGE - 18, - LauncherError::ReadPayloadSizeProhibitive => LAUNCHER_ERROR_START_RANGE - 19, - LauncherError::LocalConfigAccessFailed(_) => LAUNCHER_ERROR_START_RANGE - 20, - LauncherError::Unexpected(_) => LAUNCHER_ERROR_START_RANGE - 21, - LauncherError::UnsuccessfulEncodeDecode(_) => LAUNCHER_ERROR_START_RANGE - 22, + LauncherError::CoreError(error) => (*error).into(), + LauncherError::NfsError(error) => (*error).into(), + LauncherError::DnsError(error) => (*error).into(), + LauncherError::IpcListenerCouldNotBeBound => LAUNCHER_ERROR_START_RANGE - 1, + LauncherError::IpcListenerAborted(_) => LAUNCHER_ERROR_START_RANGE - 2, + LauncherError::IpcStreamCloneError(_) => LAUNCHER_ERROR_START_RANGE - 3, + LauncherError::ReceiverChannelDisconnected => LAUNCHER_ERROR_START_RANGE - 4, + LauncherError::IpcSessionTerminated(_) => LAUNCHER_ERROR_START_RANGE - 5, + LauncherError::FailedReadingStreamPayloadSize => LAUNCHER_ERROR_START_RANGE - 6, + LauncherError::FailedWritingStreamPayloadSize => LAUNCHER_ERROR_START_RANGE - 7, + LauncherError::PathNotFound => LAUNCHER_ERROR_START_RANGE - 8, + LauncherError::InvalidPath => LAUNCHER_ERROR_START_RANGE - 9, + LauncherError::PermissionDenied => LAUNCHER_ERROR_START_RANGE - 10, + LauncherError::JsonParseError(_) => LAUNCHER_ERROR_START_RANGE - 11, + LauncherError::JsonDecodeError(_) => LAUNCHER_ERROR_START_RANGE - 12, + LauncherError::SpecificParseError(_) => LAUNCHER_ERROR_START_RANGE - 13, + LauncherError::JsonEncodeError(_) => LAUNCHER_ERROR_START_RANGE - 14, + LauncherError::SymmetricDecipherFailure => LAUNCHER_ERROR_START_RANGE - 15, + LauncherError::AppAlreadyAdded => LAUNCHER_ERROR_START_RANGE - 16, + LauncherError::AppNotRegistered => LAUNCHER_ERROR_START_RANGE - 17, + LauncherError::AppActivationFailed(_) => LAUNCHER_ERROR_START_RANGE - 18, + LauncherError::ReadPayloadSizeProhibitive => LAUNCHER_ERROR_START_RANGE - 19, + LauncherError::LocalConfigAccessFailed(_) => LAUNCHER_ERROR_START_RANGE - 20, + LauncherError::Unexpected(_) => LAUNCHER_ERROR_START_RANGE - 21, + LauncherError::UnsuccessfulEncodeDecode(_) => LAUNCHER_ERROR_START_RANGE - 22, } } } -impl ::std::fmt::Debug for LauncherError { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl fmt::Debug for LauncherError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - LauncherError::CoreError(ref error) => write!(f, "LauncherError::CoreError -> {:?}", error), - LauncherError::NfsError(ref error) => write!(f, "LauncherError::NfsError -> {:?}", error), - LauncherError::DnsError(ref error) => write!(f, "LauncherError::DnsError -> {:?}", error), - LauncherError::IpcListenerCouldNotBeBound => write!(f, "LauncherError::IpcListenerCouldNotBeBound"), - LauncherError::IpcListenerAborted(ref error) => write!(f, "LauncherError::IpcListenerAborted -> {:?}", error), - LauncherError::IpcStreamCloneError(ref error) => write!(f, "LauncherError::IpcStreamCloneError -> {:?}", error), - LauncherError::ReceiverChannelDisconnected => write!(f, "LauncherError::ReceiverChannelDisconnected"), - LauncherError::IpcSessionTerminated(ref error) => write!(f, "LauncherError::IpcSessionTerminated -> {:?}", error), - LauncherError::FailedReadingStreamPayloadSize => write!(f, "LauncherError::FailedReadingStreamPayloadSize"), - LauncherError::FailedWritingStreamPayloadSize => write!(f, "LauncherError::FailedWritingStreamPayloadSize"), - LauncherError::PathNotFound => write!(f, "LauncherError::PathNotFound"), - LauncherError::InvalidPath => write!(f, "LauncherError::InvalidPath"), - LauncherError::PermissionDenied => write!(f, "LauncherError::PermissionDenied"), - LauncherError::JsonParseError(ref error) => write!(f, "LauncherError::JsonParseError -> {:?}", error), - LauncherError::JsonDecodeError(ref error) => write!(f, "LauncherError::JsonDecodeError -> {:?}", error), - LauncherError::SpecificParseError(ref error) => write!(f, "LauncherError::SpecificParseError -> {:?}", error), - LauncherError::JsonEncodeError(ref error) => write!(f, "LauncherError::JsonEncodeError -> {:?}", error), - LauncherError::SymmetricDecipherFailure => write!(f, "LauncherError::SymmetricDecipherFailure"), - LauncherError::AppAlreadyAdded => write!(f, "LauncherError::AppAlreadyAdded"), - LauncherError::AppNotRegistered => write!(f, "LauncherError::AppNotRegistered"), - LauncherError::AppActivationFailed(ref error) => write!(f, "LauncherError::AppActivationFailed -> {:?}", error), - LauncherError::ReadPayloadSizeProhibitive => write!(f, "LauncherError::ReadPayloadSizeProhibitive"), - LauncherError::LocalConfigAccessFailed(ref error) => write!(f, "LauncherError::LocalConfigAccessFailed -> {:?}", error), - LauncherError::Unexpected(ref error) => write!(f, "LauncherError::Unexpected{{{:?}}}", error), - LauncherError::UnsuccessfulEncodeDecode(ref err) => write!(f, "LauncherError::UnsuccessfulEncodeDecode -> {:?}", err), + LauncherError::CoreError(ref error) => { + write!(f, "LauncherError::CoreError -> {:?}", error) + } + LauncherError::NfsError(ref error) => { + write!(f, "LauncherError::NfsError -> {:?}", error) + } + LauncherError::DnsError(ref error) => { + write!(f, "LauncherError::DnsError -> {:?}", error) + } + LauncherError::IpcListenerCouldNotBeBound => { + write!(f, "LauncherError::IpcListenerCouldNotBeBound") + } + LauncherError::IpcListenerAborted(ref error) => { + write!(f, "LauncherError::IpcListenerAborted -> {:?}", error) + } + LauncherError::IpcStreamCloneError(ref error) => { + write!(f, "LauncherError::IpcStreamCloneError -> {:?}", error) + } + LauncherError::ReceiverChannelDisconnected => { + write!(f, "LauncherError::ReceiverChannelDisconnected") + } + LauncherError::IpcSessionTerminated(ref error) => { + write!(f, "LauncherError::IpcSessionTerminated -> {:?}", error) + } + LauncherError::FailedReadingStreamPayloadSize => { + write!(f, "LauncherError::FailedReadingStreamPayloadSize") + } + LauncherError::FailedWritingStreamPayloadSize => { + write!(f, "LauncherError::FailedWritingStreamPayloadSize") + } + LauncherError::PathNotFound => write!(f, "LauncherError::PathNotFound"), + LauncherError::InvalidPath => write!(f, "LauncherError::InvalidPath"), + LauncherError::PermissionDenied => write!(f, "LauncherError::PermissionDenied"), + LauncherError::JsonParseError(ref error) => { + write!(f, "LauncherError::JsonParseError -> {:?}", error) + } + LauncherError::JsonDecodeError(ref error) => { + write!(f, "LauncherError::JsonDecodeError -> {:?}", error) + } + LauncherError::SpecificParseError(ref error) => { + write!(f, "LauncherError::SpecificParseError -> {:?}", error) + } + LauncherError::JsonEncodeError(ref error) => { + write!(f, "LauncherError::JsonEncodeError -> {:?}", error) + } + LauncherError::SymmetricDecipherFailure => { + write!(f, "LauncherError::SymmetricDecipherFailure") + } + LauncherError::AppAlreadyAdded => write!(f, "LauncherError::AppAlreadyAdded"), + LauncherError::AppNotRegistered => write!(f, "LauncherError::AppNotRegistered"), + LauncherError::AppActivationFailed(ref error) => { + write!(f, "LauncherError::AppActivationFailed -> {:?}", error) + } + LauncherError::ReadPayloadSizeProhibitive => { + write!(f, "LauncherError::ReadPayloadSizeProhibitive") + } + LauncherError::LocalConfigAccessFailed(ref error) => { + write!(f, "LauncherError::LocalConfigAccessFailed -> {:?}", error) + } + LauncherError::Unexpected(ref error) => { + write!(f, "LauncherError::Unexpected{{{:?}}}", error) + } + LauncherError::UnsuccessfulEncodeDecode(ref err) => { + write!(f, "LauncherError::UnsuccessfulEncodeDecode -> {:?}", err) + } } } } diff --git a/src/ffi/errors.rs b/src/ffi/errors.rs index 0f00813d..709cd831 100644 --- a/src/ffi/errors.rs +++ b/src/ffi/errors.rs @@ -15,36 +15,43 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. -const FFI_ERROR_START_RANGE: i32 = ::errors::LAUNCHER_ERROR_START_RANGE - 500; +use std::fmt; + +use safe_core::errors::CoreError; +use errors::{LAUNCHER_ERROR_START_RANGE, LauncherError}; + +const FFI_ERROR_START_RANGE: i32 = LAUNCHER_ERROR_START_RANGE - 500; /// Errors during FFI operations pub enum FfiError { /// Errors from Safe Core - CoreError(Box<::safe_core::errors::CoreError>), + CoreError(Box), /// Errors from Launcher - LauncherError(Box<::errors::LauncherError>), + LauncherError(Box), /// Unexpected or some programming error Unexpected(String), } -impl ::std::fmt::Debug for FfiError { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl fmt::Debug for FfiError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - FfiError::CoreError(ref error) => write!(f, "FfiError::CoreError -> {:?}", error), - FfiError::LauncherError(ref error) => write!(f, "FfiError::LauncherError -> {:?}", error), - FfiError::Unexpected(ref error) => write!(f, "FfiError::Unexpected::{{{:?}}}", error), + FfiError::CoreError(ref error) => write!(f, "FfiError::CoreError -> {:?}", error), + FfiError::LauncherError(ref error) => { + write!(f, "FfiError::LauncherError -> {:?}", error) + } + FfiError::Unexpected(ref error) => write!(f, "FfiError::Unexpected::{{{:?}}}", error), } } } -impl From<::errors::LauncherError> for FfiError { - fn from(error: ::errors::LauncherError) -> FfiError { +impl From for FfiError { + fn from(error: LauncherError) -> FfiError { FfiError::LauncherError(Box::new(error)) } } -impl From<::safe_core::errors::CoreError> for FfiError { - fn from(error: ::safe_core::errors::CoreError) -> FfiError { +impl From for FfiError { + fn from(error: CoreError) -> FfiError { FfiError::CoreError(Box::new(error)) } } @@ -58,9 +65,9 @@ impl<'a> From<&'a str> for FfiError { impl Into for FfiError { fn into(self) -> i32 { match self { - FfiError::CoreError(error) => (*error).into(), - FfiError::LauncherError(error) => (*error).into(), - FfiError::Unexpected(_) => FFI_ERROR_START_RANGE - 1, + FfiError::CoreError(error) => (*error).into(), + FfiError::LauncherError(error) => (*error).into(), + FfiError::Unexpected(_) => FFI_ERROR_START_RANGE - 1, } } } diff --git a/src/ffi/implementation.rs b/src/ffi/implementation.rs index 25201861..83768f3a 100644 --- a/src/ffi/implementation.rs +++ b/src/ffi/implementation.rs @@ -15,11 +15,18 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use libc::c_char; + +use std::ffi::CStr; + +use ffi::errors::FfiError; + /// Converts c character pointer into Rust String #[allow(unsafe_code)] -pub fn c_char_ptr_to_string(c_char_ptr: *const ::libc::c_char) -> Result { - use ::std::error::Error; +pub fn c_char_ptr_to_string(c_char_ptr: *const c_char) -> Result { + use std::error::Error; - let cstr = unsafe { ::std::ffi::CStr::from_ptr(c_char_ptr) }; - Ok(try!(String::from_utf8(cstr.to_bytes().iter().map(|a| *a).collect()).map_err(|error| ::ffi::errors::FfiError::from(error.description())))) + let cstr = unsafe { CStr::from_ptr(c_char_ptr) }; + Ok(try!(String::from_utf8(cstr.to_bytes().iter().map(|a| *a).collect()) + .map_err(|error| FfiError::from(error.description())))) } diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index cde810cd..052e5f98 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -18,69 +18,85 @@ mod errors; mod implementation; +use std::mem; + +use libc::{c_char, c_void, int32_t}; + +use safe_core::client::Client; + +use launcher::Launcher; + /// Create an account with SafeNetwork. This or any one of the other companion functions to get a -/// launcher must be called before initiating any operation allowed by this crate. `launcher_handle` is -/// a pointer to a pointer and must point to a valid pointer not junk, else the consequences are +/// launcher must be called before initiating any operation allowed by this crate. `launcher_handle` +/// is a pointer to a pointer and must point to a valid pointer not junk, else the consequences are /// undefined. #[no_mangle] #[allow(unsafe_code)] -pub extern fn create_account(c_keyword : *const ::libc::c_char, - c_pin : *const ::libc::c_char, - c_password : *const ::libc::c_char, - launcher_handle: *mut *const ::libc::c_void) -> ::libc::int32_t { - let client = ffi_try!(::safe_core::client::Client::create_account(ffi_try!(implementation::c_char_ptr_to_string(c_keyword)), - ffi_try!(implementation::c_char_ptr_to_string(c_pin)), - ffi_try!(implementation::c_char_ptr_to_string(c_password)))); - let launcher = ffi_try!(::launcher::Launcher::new(client)); - unsafe { *launcher_handle = cast_to_launcher_ffi_handle(launcher); } +pub extern "C" fn create_account(c_keyword: *const c_char, + c_pin: *const c_char, + c_password: *const c_char, + launcher_handle: *mut *const c_void) + -> int32_t { + let client = ffi_try!(Client::create_account( + ffi_try!(implementation::c_char_ptr_to_string(c_keyword)), + ffi_try!(implementation::c_char_ptr_to_string(c_pin)), + ffi_try!(implementation::c_char_ptr_to_string(c_password)))); + let launcher = ffi_try!(Launcher::new(client)); + unsafe { + *launcher_handle = cast_to_launcher_ffi_handle(launcher); + } 0 } -/// Log into Safenetwork with an already registered account. This or any one of the other companion functions to get a -/// launcher must be called before initiating any operation allowed by this crate. `launcher_handle` is -/// a pointer to a pointer and must point to a valid pointer not junk, else the consequences are -/// undefined. +/// Log into Safenetwork with an already registered account. This or any one of the other companion +/// functions to get a launcher must be called before initiating any operation allowed by this +/// crate. `launcher_handle` is a pointer to a pointer and must point to a valid pointer not junk, +/// else the consequences are undefined. #[no_mangle] #[allow(unsafe_code)] -pub extern fn log_in(c_keyword : *const ::libc::c_char, - c_pin : *const ::libc::c_char, - c_password : *const ::libc::c_char, - launcher_handle: *mut *const ::libc::c_void) -> ::libc::int32_t { - let client = ffi_try!(::safe_core::client::Client::log_in(ffi_try!(implementation::c_char_ptr_to_string(c_keyword)), - ffi_try!(implementation::c_char_ptr_to_string(c_pin)), - ffi_try!(implementation::c_char_ptr_to_string(c_password)))); - let launcher = ffi_try!(::launcher::Launcher::new(client)); - unsafe { *launcher_handle = cast_to_launcher_ffi_handle(launcher); } +pub extern "C" fn log_in(c_keyword: *const c_char, + c_pin: *const c_char, + c_password: *const c_char, + launcher_handle: *mut *const c_void) + -> int32_t { + let client = ffi_try!(Client::log_in( + ffi_try!(implementation::c_char_ptr_to_string(c_keyword)), + ffi_try!(implementation::c_char_ptr_to_string(c_pin)), + ffi_try!(implementation::c_char_ptr_to_string(c_password)))); + let launcher = ffi_try!(Launcher::new(client)); + unsafe { + *launcher_handle = cast_to_launcher_ffi_handle(launcher); + } 0 } -/// Discard and clean up the previously allocated launcher. Use this only if the launcher is obtained -/// from one of the client obtainment functions in this crate (`create_account`, `log_in`). -/// Using `launcher_handle` after a call to this functions is undefined behaviour. +/// Discard and clean up the previously allocated launcher. Use this only if the launcher is +/// obtained from one of the client obtainment functions in this crate (`create_account`, +/// `log_in`). Using `launcher_handle` after a call to this functions is undefined behaviour. #[no_mangle] #[allow(unsafe_code)] -pub extern fn drop_launcher(launcher_handle: *const ::libc::c_void) { - let _ = unsafe { ::std::mem::transmute::<_, Box<::launcher::Launcher>>(launcher_handle) }; +pub extern "C" fn drop_launcher(launcher_handle: *const c_void) { + let _ = unsafe { mem::transmute::<_, Box>(launcher_handle) }; } #[allow(unsafe_code)] -fn cast_to_launcher_ffi_handle(launcher: ::launcher::Launcher) -> *const ::libc::c_void { +fn cast_to_launcher_ffi_handle(launcher: Launcher) -> *const c_void { let boxed_launcher = Box::new(launcher); - unsafe { ::std::mem::transmute(boxed_launcher) } + unsafe { mem::transmute(boxed_launcher) } } // TODO(Spandan) ***W A R N I N G*** This will be UB - make sure to modify after uncommenting // #[allow(unsafe_code)] -// fn cast_from_launcher_ffi_handle(launcher_handle: *const ::libc::c_void) -> ::launcher::Launcher { +// fn cast_from_launcher_ffi_handle(launcher_handle: *const c_void) -> Launcher { // let boxed_launcher: Box<::launcher::Launcher> = unsafe { -// ::std::mem::transmute(launcher_handle) +// mem::transmute(launcher_handle) // }; -// +// // let launcher = *boxed_launcher; -// ::std::mem::forget(boxed_launcher); -// +// mem::forget(boxed_launcher); +// // launcher // } @@ -88,10 +104,14 @@ fn cast_to_launcher_ffi_handle(launcher: ::launcher::Launcher) -> *const ::libc: #[cfg(test)] mod test { use super::*; - use ::std::error::Error; - - fn generate_random_cstring(len: usize) -> Result<::std::ffi::CString, ::ffi::errors::FfiError> { - let mut cstring_vec = unwrap_result!(::safe_core::utility::generate_random_vector::(len)); + use libc::c_void; + use std::error::Error; + use std::ffi::CString; + use ffi::errors::FfiError; + use safe_core::utility; + + fn generate_random_cstring(len: usize) -> Result { + let mut cstring_vec = unwrap_result!(utility::generate_random_vector::(len)); // Avoid internal nulls and ensure valid ASCII (thus valid utf8) for it in cstring_vec.iter_mut() { *it %= 128; @@ -100,7 +120,7 @@ mod test { } } - ::std::ffi::CString::new(cstring_vec).map_err(|error| ::ffi::errors::FfiError::from(error.description())) + CString::new(cstring_vec).map_err(|error| FfiError::from(error.description())) } #[test] @@ -110,8 +130,8 @@ mod test { let cstring_password = unwrap_result!(generate_random_cstring(10)); { - let mut launcher_handle = 0 as *const ::libc::c_void; - assert_eq!(launcher_handle, 0 as *const ::libc::c_void); + let mut launcher_handle = 0 as *const c_void; + assert_eq!(launcher_handle, 0 as *const c_void); { let ptr_to_launcher_handle = &mut launcher_handle; @@ -123,13 +143,13 @@ mod test { 0); } - assert!(launcher_handle != 0 as *const ::libc::c_void); + assert!(launcher_handle != 0 as *const c_void); drop_launcher(launcher_handle); } { - let mut launcher_handle = 0 as *const ::libc::c_void; - assert_eq!(launcher_handle, 0 as *const ::libc::c_void); + let mut launcher_handle = 0 as *const c_void; + assert_eq!(launcher_handle, 0 as *const c_void); { let ptr_to_launcher_handle = &mut launcher_handle; @@ -141,7 +161,7 @@ mod test { 0); } - assert!(launcher_handle != 0 as *const ::libc::c_void); + assert!(launcher_handle != 0 as *const c_void); drop_launcher(launcher_handle); } } diff --git a/src/launcher/app_handler/events.rs b/src/launcher/app_handler/events.rs index 18f1033e..2400b122 100644 --- a/src/launcher/app_handler/events.rs +++ b/src/launcher/app_handler/events.rs @@ -15,6 +15,11 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::fmt; +use std::sync::mpsc; + +use errors::LauncherError; +use observer::AppHandlerObserver; use xor_name::XorName; /// This is an event subset to be used by external codes to communicate with the App Handling @@ -29,27 +34,27 @@ pub enum AppHandlerEvent { /// Modify settings for an app ModifyAppSettings(event_data::ModifyAppSettings), /// Register an observer to receive notifications about status of adding of an app. - RegisterAppAddObserver(::observer::AppHandlerObserver), + RegisterAppAddObserver(AppHandlerObserver), /// Register an observer to receive notifications about status of removal of an app. - RegisterAppRemoveObserver(::observer::AppHandlerObserver), + RegisterAppRemoveObserver(AppHandlerObserver), /// Register an observer to receive notifications about an app being activated. Note however /// that a successful activation does not necessarily translate into successfully managed /// session. It just means that app has been started. It can still crash after start, fail /// authentication etc. Register obeservers in IPC module to get a more fine grained /// information. - RegisterAppActivateObserver(::observer::AppHandlerObserver), + RegisterAppActivateObserver(AppHandlerObserver), /// Register an observer to receive notifications about status of modification of an app. - RegisterAppModifyObserver(::observer::AppHandlerObserver), + RegisterAppModifyObserver(AppHandlerObserver), /// Obtain all apps currently being managed by Launcher. - GetAllManagedApps(::std::sync::mpsc::Sender, ::errors::LauncherError>>), + GetAllManagedApps(mpsc::Sender, LauncherError>>), /// Gracefully exit the app handling module. After a call to this Launcher will no longer cater /// to any requests handled by this module. This is essentially Launcher-close scenario and /// Launcher must be restarted to be functional again. Terminate, } -impl ::std::fmt::Debug for AppHandlerEvent { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl fmt::Debug for AppHandlerEvent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", *self) } } @@ -76,7 +81,7 @@ pub mod event_data { #[derive(Debug, Clone)] pub struct AppDetail { /// Absolute path to the app binary on this machine. - pub absolute_path : String, + pub absolute_path: String, /// If this app is allowed to have access to `SAFEDrive`. pub safe_drive_access: bool, } @@ -85,16 +90,16 @@ pub mod event_data { #[derive(Debug, Clone)] pub struct ManagedApp { /// Unique id given to the app. This will be consistent across all machines. - pub id : XorName, + pub id: XorName, /// Name of this app. Unless specifically changed it will be the name of the binary added /// to Launcher in the first machine for this app. - pub name : String, + pub name: String, /// If the app was added to this machine, this will contain the absolute path to the /// application binary. Otherwise it will be `None` indicating that app was added to /// Launcher but not yet on this machine. - pub local_path : Option, + pub local_path: Option, /// Number of machines this app is currently added to Launcher in. - pub reference_count : u32, + pub reference_count: u32, /// If this app is allowed to have access to `SAFEDrive`. pub safe_drive_access: bool, } @@ -104,11 +109,11 @@ pub mod event_data { #[derive(Debug, Clone)] pub struct ModifyAppSettings { /// Unique id given to the app. This will be consistent across all machines. - pub id : XorName, + pub id: XorName, /// App name for this app stored in Launcher. - pub name : Option, + pub name: Option, /// Modify local binary absolute path. - pub local_path : Option, + pub local_path: Option, /// If this app is allowed to have access to `SAFEDrive`. pub safe_drive_access: Option, } diff --git a/src/launcher/app_handler/misc.rs b/src/launcher/app_handler/misc.rs index 672ac52a..1fe488cd 100644 --- a/src/launcher/app_handler/misc.rs +++ b/src/launcher/app_handler/misc.rs @@ -15,67 +15,79 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::collections::HashMap; +use std::fs::File; +use std::path; + +use errors::LauncherError; +use safe_nfs::metadata::directory_key::DirectoryKey; use xor_name::XorName; #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct LauncherConfiguration { - pub app_id : XorName, - pub app_name : String, - pub reference_count : u32, - pub app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, + pub app_id: XorName, + pub app_name: String, + pub reference_count: u32, + pub app_root_dir_key: DirectoryKey, pub safe_drive_access: bool, } // (Spandan) // This is a hack because presently cbor isn't able to decode/encode HashMap // properly -pub fn convert_hashmap_to_vec(hashmap: &::std::collections::HashMap) -> Vec<(XorName, String)> { +pub fn convert_hashmap_to_vec(hashmap: &HashMap) -> Vec<(XorName, String)> { hashmap.iter().map(|a| (a.0.clone(), a.1.clone())).collect() } // (Spandan) // This is a hack because presently cbor isn't able to decode/encode HashMap // properly -pub fn convert_vec_to_hashmap(vec: Vec<(XorName, String)>) -> ::std::collections::HashMap { +pub fn convert_vec_to_hashmap(vec: Vec<(XorName, String)>) -> HashMap { vec.into_iter().collect() } -pub fn read_local_config_file() -> Result, ::errors::LauncherError> { +pub fn read_local_config_file() -> Result, LauncherError> { use std::io::Read; let path = try!(get_local_config_file()); - match ::std::fs::File::open(path) { + match File::open(path) { Ok(mut file) => { - let mut raw_disk_data = Vec::with_capacity(unwrap_result!(file.metadata()).len() as usize); + let mut raw_disk_data = + Vec::with_capacity(unwrap_result!(file.metadata()).len() as usize); match file.read_to_end(&mut raw_disk_data) { Ok(_) => return Ok(raw_disk_data), Err(err) => debug!("{:?} - Unable to open local config file", err), } - }, + } Err(err) => debug!("{:?} - Unable to open local config file", err), } Ok(Vec::new()) } -pub fn flush_to_local_config(raw_data: &[u8]) -> Result<(), ::errors::LauncherError> { +pub fn flush_to_local_config(raw_data: &[u8]) -> Result<(), LauncherError> { use std::io::Write; let path = try!(get_local_config_file()); - let mut file = try!(::std::fs::File::create(path).map_err(|e| ::errors - ::LauncherError - ::LocalConfigAccessFailed(format!("{:?} - Unable to create.", e)))); - try!(file.write_all(&raw_data).map_err(|e| ::errors::LauncherError::LocalConfigAccessFailed(format!("{:?} - Unable to write.", e)))); + let mut file = try!(File::create(path).map_err(|e| { + LauncherError::LocalConfigAccessFailed(format!("{:?} - Unable to create.", e)) + })); + try!(file.write_all(&raw_data).map_err(|e| { + LauncherError::LocalConfigAccessFailed(format!("{:?} - Unable to write.", e)) + })); - Ok(try!(file.sync_all().map_err(|e| ::errors::LauncherError::LocalConfigAccessFailed(format!("{:?} - Unable to sync.", e))))) + Ok(try!(file.sync_all().map_err(|e| { + LauncherError::LocalConfigAccessFailed(format!("{:?} - Unable to sync.", e)) + }))) } -fn get_local_config_file() -> Result<::std::path::PathBuf, ::errors::LauncherError> { - let mut config_dir_pathbuf = try!(::std::env::home_dir().ok_or(::errors - ::LauncherError - ::LocalConfigAccessFailed("Unable to get user's Home Directory.".to_string()))); +fn get_local_config_file() -> Result { + let mut config_dir_pathbuf = try!(::std::env::home_dir() + .ok_or(LauncherError::LocalConfigAccessFailed("Unable to get user's \ + Home Directory." + .to_string()))); config_dir_pathbuf.push(::config::LAUNCHER_LOCAL_CONFIG_FILE_NAME); Ok(config_dir_pathbuf) diff --git a/src/launcher/app_handler/mod.rs b/src/launcher/app_handler/mod.rs index 76d0f929..eec9f291 100644 --- a/src/launcher/app_handler/mod.rs +++ b/src/launcher/app_handler/mod.rs @@ -17,69 +17,90 @@ pub mod events; +use std::collections::HashMap; +use std::process::Command; +use std::sync::{Arc, mpsc, Mutex}; + use xor_name::XorName; use maidsafe_utilities::thread::RaiiThreadJoiner; use maidsafe_utilities::serialisation::{serialise, deserialise}; +use config::{LAUNCHER_GLOBAL_CONFIG_FILE_NAME, LAUNCHER_GLOBAL_DIRECTORY_NAME, + LAUNCHER_NONCE_LENGTH}; +use errors::LauncherError; +use launcher::ipc_server::EventSenderToServer; +use launcher::ipc_server::events::{event_data, ExternalEvent}; +use observer::AppHandlerObserver; +use observer::event_data::{AppAddition, AppAdditionData, AppModification, AppRemoval, + ModificationDetail}; +use safe_core::client::Client; +use safe_core::utility; +use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; +use safe_nfs::helper::directory_helper::DirectoryHelper; +use safe_nfs::directory_listing::DirectoryListing; +use safe_nfs::helper::file_helper::FileHelper; +use safe_nfs::helper::writer::Mode::Overwrite; + mod misc; const APP_HANDLER_THREAD_NAME: &'static str = "AppHandlerThread"; pub struct AppHandler { - client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - launcher_endpoint : String, - local_config_data : ::std::collections::HashMap, - app_add_observers : Vec<::observer::AppHandlerObserver>, - app_remove_observers : Vec<::observer::AppHandlerObserver>, - app_modify_observers : Vec<::observer::AppHandlerObserver>, - app_activate_observers : Vec<::observer::AppHandlerObserver>, - ipc_server_event_sender: ::launcher - ::ipc_server - ::EventSenderToServer<::launcher - ::ipc_server - ::events::ExternalEvent>, + client: Arc>, + launcher_endpoint: String, + local_config_data: HashMap, + app_add_observers: Vec, + app_remove_observers: Vec, + app_modify_observers: Vec, + app_activate_observers: Vec, + ipc_server_event_sender: EventSenderToServer, } impl AppHandler { - pub fn new(client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - event_sender: ::launcher - ::ipc_server - ::EventSenderToServer<::launcher - ::ipc_server - ::events::ExternalEvent>) -> (RaiiThreadJoiner, - ::std::sync::mpsc::Sender) { - let (event_tx, event_rx) = ::std::sync::mpsc::channel(); + pub fn new(client: Arc>, + event_sender: EventSenderToServer) + -> (RaiiThreadJoiner, mpsc::Sender) { + let (event_tx, event_rx) = mpsc::channel(); let joiner = thread!(APP_HANDLER_THREAD_NAME, move || { let raw_disk_data = unwrap_result!(misc::read_local_config_file()); - let mut local_config_data = ::std::collections::HashMap::with_capacity(raw_disk_data.len() + 1); + let mut local_config_data = HashMap::with_capacity(raw_disk_data.len() + 1); if raw_disk_data.len() != 0 { match unwrap_result!(client.lock()).hybrid_decrypt(&raw_disk_data, None) { - Ok(plain_text) => local_config_data = misc::convert_vec_to_hashmap(unwrap_result!(deserialise(&plain_text))), - Err(err) => debug!("{:?} -> Local config file could not be read - either tampered or corrupted. Starting afresh...", err), + Ok(plain_text) => { + local_config_data = + misc::convert_vec_to_hashmap(unwrap_result!(deserialise(&plain_text))) + } + Err(err) => { + debug!("{:?} -> Local config file could not be read - either tampered or \ + corrupted. Starting afresh...", + err) + } } } - let (tx, rx) = ::std::sync::mpsc::channel(); - if event_sender.send(::launcher::ipc_server::events::ExternalEvent::GetListenerEndpoint(tx)).is_ok() { + let (tx, rx) = mpsc::channel(); + if event_sender.send(ExternalEvent::GetListenerEndpoint(tx)).is_ok() { if let Ok(launcher_endpoint) = rx.recv() { let mut app_handler = AppHandler { - client : client, - launcher_endpoint : launcher_endpoint, - local_config_data : local_config_data, - app_add_observers : Vec::with_capacity(2), - app_remove_observers : Vec::with_capacity(2), - app_modify_observers : Vec::with_capacity(2), - app_activate_observers : Vec::with_capacity(2), + client: client, + launcher_endpoint: launcher_endpoint, + local_config_data: local_config_data, + app_add_observers: Vec::with_capacity(2), + app_remove_observers: Vec::with_capacity(2), + app_modify_observers: Vec::with_capacity(2), + app_activate_observers: Vec::with_capacity(2), ipc_server_event_sender: event_sender, }; app_handler.run(event_rx); } else { - debug!("AppHandler <-> IPC-Server Communication failed - Probably Launcher was closed too soon."); + debug!("AppHandler <-> IPC-Server Communication failed - Probably Launcher \ + was closed too soon."); } } else { - debug!("AppHandler <-> IPC-Server Communication failed - Probably Launcher was closed too soon."); + debug!("AppHandler <-> IPC-Server Communication failed - Probably Launcher was \ + closed too soon."); } debug!("Exiting thread {:?}", APP_HANDLER_THREAD_NAME); @@ -88,18 +109,30 @@ impl AppHandler { (RaiiThreadJoiner::new(joiner), event_tx) } - fn run(&mut self, event_rx: ::std::sync::mpsc::Receiver) { + fn run(&mut self, event_rx: mpsc::Receiver) { for event in event_rx.iter() { match event { - events::AppHandlerEvent::AddApp(app_detail) => self.on_add_app(app_detail), - events::AppHandlerEvent::RemoveApp(app_id) => self.on_remove_app(app_id), - events::AppHandlerEvent::ActivateApp(app_id) => self.on_activate_app(app_id), - events::AppHandlerEvent::GetAllManagedApps(obs) => self.on_get_all_managed_apps(obs), - events::AppHandlerEvent::ModifyAppSettings(data) => self.on_modify_app_settings(data), - events::AppHandlerEvent::RegisterAppAddObserver(obs) => self.on_register_app_add_observer(obs), - events::AppHandlerEvent::RegisterAppRemoveObserver(obs) => self.on_register_app_remove_observer(obs), - events::AppHandlerEvent::RegisterAppModifyObserver(obs) => self.on_register_app_modify_observer(obs), - events::AppHandlerEvent::RegisterAppActivateObserver(obs) => self.on_register_app_activate_observer(obs), + events::AppHandlerEvent::AddApp(app_detail) => self.on_add_app(app_detail), + events::AppHandlerEvent::RemoveApp(app_id) => self.on_remove_app(app_id), + events::AppHandlerEvent::ActivateApp(app_id) => self.on_activate_app(app_id), + events::AppHandlerEvent::GetAllManagedApps(obs) => { + self.on_get_all_managed_apps(obs) + } + events::AppHandlerEvent::ModifyAppSettings(data) => { + self.on_modify_app_settings(data) + } + events::AppHandlerEvent::RegisterAppAddObserver(obs) => { + self.on_register_app_add_observer(obs) + } + events::AppHandlerEvent::RegisterAppRemoveObserver(obs) => { + self.on_register_app_remove_observer(obs) + } + events::AppHandlerEvent::RegisterAppModifyObserver(obs) => { + self.on_register_app_modify_observer(obs) + } + events::AppHandlerEvent::RegisterAppActivateObserver(obs) => { + self.on_register_app_activate_observer(obs) + } events::AppHandlerEvent::Terminate => break, } } @@ -110,79 +143,91 @@ impl AppHandler { let reply = match self.on_add_app_impl(app_detail) { Ok(data) => data, - Err(err) => ::observer::event_data::AppAddition { - result : Err(err), - local_path: abs_path, - }, + Err(err) => { + AppAddition { + result: Err(err), + local_path: abs_path, + } + } }; group_send!(reply, &mut self.app_add_observers); } - fn on_add_app_impl(&mut self, app_detail: events::event_data::AppDetail) -> Result<::observer::event_data::AppAddition, - ::errors::LauncherError> { + fn on_add_app_impl(&mut self, + app_detail: events::event_data::AppDetail) + -> Result { { let mut paths = self.local_config_data.values(); if let Some(_) = paths.find(|stored_path| **stored_path == app_detail.absolute_path) { - return Err(::errors::LauncherError::AppAlreadyAdded) + return Err(LauncherError::AppAlreadyAdded); } } - let app_id = XorName::new(try!(::safe_core::utility::generate_random_array_u8_64())); + let app_id = XorName::new(try!(utility::generate_random_array_u8_64())); let mut tokens = AppHandler::tokenise_path(&app_detail.absolute_path); - let app_name = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); + let app_name = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(self.client.clone()); + let dir_helper = DirectoryHelper::new(self.client.clone()); let mut root_dir_listing = try!(dir_helper.get_user_root_directory_listing()); let app_dir_name = AppHandler::get_app_dir_name(&app_name, &root_dir_listing); - let app_root_dir_key = match root_dir_listing.find_sub_directory(&app_dir_name).map(|dir| dir.clone()) { + let app_root_dir_key = match root_dir_listing.find_sub_directory(&app_dir_name) + .map(|dir| dir.clone()) { Some(app_dir) => app_dir.get_key().clone(), None => { try!(dir_helper.create(app_dir_name, - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, + UNVERSIONED_DIRECTORY_LISTING_TAG, Vec::new(), false, - ::safe_nfs::AccessLevel::Private, - Some(&mut root_dir_listing))).0.get_key().clone() - }, + AccessLevel::Private, + Some(&mut root_dir_listing))) + .0 + .get_key() + .clone() + } }; let new_launcher_config = misc::LauncherConfiguration { - app_id : app_id, - app_name : app_name.clone(), - reference_count : 1, - app_root_dir_key : app_root_dir_key, + app_id: app_id, + app_name: app_name.clone(), + reference_count: 1, + app_root_dir_key: app_root_dir_key, safe_drive_access: app_detail.safe_drive_access, }; try!(self.upsert_to_launcher_global_config(new_launcher_config)); let _ = self.local_config_data.insert(app_id, app_detail.absolute_path.clone()); - let app_addition_data = ::observer::event_data::AppAdditionData { - id : app_id, + let app_addition_data = AppAdditionData { + id: app_id, name: app_name, }; - Ok(::observer::event_data::AppAddition { - result : Ok(app_addition_data), + Ok(AppAddition { + result: Ok(app_addition_data), local_path: app_detail.absolute_path, }) } fn on_activate_app(&mut self, app_id: XorName) { - let event = ::observer::AppHandlingEvent::AppActivation(self.on_activate_app_impl(app_id).map(|()| app_id)); + use observer::AppHandlingEvent::AppActivation; + let event = AppActivation(self.on_activate_app_impl(app_id).map(|()| app_id)); group_send!(event, &mut self.app_activate_observers); } - fn on_activate_app_impl(&self, app_id: XorName) -> Result<(), ::errors::LauncherError> { + fn on_activate_app_impl(&self, app_id: XorName) -> Result<(), LauncherError> { let global_configs = try!(self.get_launcher_global_config()); - let app_info = try!(global_configs.iter().find(|config| config.app_id == app_id).ok_or(::errors::LauncherError::AppNotRegistered)); - let app_binary_path = try!(self.local_config_data.get(&app_info.app_id).ok_or(::errors::LauncherError::PathNotFound)); + let app_info = try!(global_configs.iter() + .find(|config| config.app_id == app_id) + .ok_or(LauncherError::AppNotRegistered)); + let app_binary_path = try!(self.local_config_data + .get(&app_info.app_id) + .ok_or(LauncherError::PathNotFound)); - let mut rand_vec = try!(::safe_core::utility::generate_random_vector::(::config::LAUNCHER_NONCE_LENGTH)); + let mut rand_vec = try!(utility::generate_random_vector::(LAUNCHER_NONCE_LENGTH)); // Ensure valid ASCII and hence valid UTF-8. Keep it in ASCII range [48, 122]. for it in rand_vec.iter_mut() { *it %= 123; @@ -190,36 +235,34 @@ impl AppHandler { *it += 48; } } - let str_nonce = try!(String::from_utf8(rand_vec).map_err(|e| ::errors - ::LauncherError - ::Unexpected(format!("{:?} -> Logic Error - Report a bug.", e)))); - - let activation_detail = ::launcher::ipc_server::events::event_data::ActivationDetail { - nonce : str_nonce.clone(), - app_id : app_info.app_id.clone(), - app_root_dir_key : app_info.app_root_dir_key.clone(), + let str_nonce = try!(String::from_utf8(rand_vec).map_err(|e| { + LauncherError::Unexpected(format!("{:?} -> Logic Error - Report a bug.", e)) + })); + + let activation_detail = event_data::ActivationDetail { + nonce: str_nonce.clone(), + app_id: app_info.app_id.clone(), + app_root_dir_key: app_info.app_root_dir_key.clone(), safe_drive_access: app_info.safe_drive_access, }; - try!(send_one!(activation_detail, - &self.ipc_server_event_sender).map_err(|e| ::errors - ::LauncherError - ::Unexpected(format!("{:?} Could not communicate activation detail \ - to IPC Server", e)))); + try!(send_one!(activation_detail, &self.ipc_server_event_sender).map_err(|e| { + ::errors::LauncherError::Unexpected(format!("{:?} Could not communicate activation \ + detail to IPC Server", + e)) + })); let command_line_arg = format!("tcp:{}:{}", self.launcher_endpoint, str_nonce); - if let Err(err) = ::std::process::Command::new(app_binary_path) - .arg("--launcher") - .arg(command_line_arg) - .spawn() { - if let Err(err) = self.ipc_server_event_sender.send(::launcher - ::ipc_server - ::events - ::ExternalEvent::EndSession(app_id)) { + if let Err(err) = Command::new(app_binary_path) + .arg("--launcher") + .arg(command_line_arg) + .spawn() { + if let Err(err) = self.ipc_server_event_sender + .send(ExternalEvent::EndSession(app_id)) { debug!("{:?} Error sending end-session signal to IPC Server.", err); } - Err(::errors::LauncherError::AppActivationFailed(err)) + Err(LauncherError::AppActivationFailed(err)) } else { Ok(()) } @@ -228,46 +271,48 @@ impl AppHandler { fn on_remove_app(&mut self, app_id: XorName) { let reply = match self.on_remove_app_impl(app_id) { Ok(data) => { - if let Err(err) = self.ipc_server_event_sender.send(::launcher - ::ipc_server - ::events - ::ExternalEvent::EndSession(app_id)) { + if let Err(err) = self.ipc_server_event_sender + .send(ExternalEvent::EndSession(app_id)) { debug!("{:?} Error sending end-session signal to IPC Server.", err); } data - }, - Err(err) => ::observer::event_data::AppRemoval { - id : app_id, - result: Some(err), - }, + } + Err(err) => { + AppRemoval { + id: app_id, + result: Some(err), + } + } }; group_send!(reply, &mut self.app_remove_observers); } - fn on_remove_app_impl(&mut self, app_id: XorName) -> Result<::observer::event_data::AppRemoval, - ::errors::LauncherError> { - let config_file_name = ::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string(); + fn on_remove_app_impl(&mut self, app_id: XorName) -> Result { + let config_file_name = LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string(); - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(self.client.clone()); - let (mut launcher_configurations, dir_listing) = try!(self.get_launcher_global_config_and_dir()); + let file_helper = FileHelper::new(self.client.clone()); + let (mut launcher_configurations, dir_listing) = + try!(self.get_launcher_global_config_and_dir()); let position = try!(launcher_configurations.iter() .position(|config| config.app_id == app_id) - .ok_or(::errors::LauncherError::AppNotRegistered)); + .ok_or(LauncherError::AppNotRegistered)); let reference_count = launcher_configurations[position].reference_count; if reference_count == 1 { let _ = launcher_configurations.remove(position); } else { - let config = try!(launcher_configurations.get_mut(position) - .ok_or(::errors::LauncherError::AppNotRegistered)); - config.reference_count -= 1; + let config = try!(launcher_configurations.get_mut(position) + .ok_or(LauncherError::AppNotRegistered)); + config.reference_count -= 1; } - let file = unwrap_option!(dir_listing.find_file(&config_file_name).map(|file| file.clone()), "Configuration file not found"); - let mut writer = try!(file_helper.update_content(file, ::safe_nfs::helper::writer::Mode::Overwrite, dir_listing)); + let file = unwrap_option!(dir_listing.find_file(&config_file_name) + .map(|file| file.clone()), + "Configuration file not found"); + let mut writer = try!(file_helper.update_content(file, Overwrite, dir_listing)); writer.write(&try!(serialise(&launcher_configurations)), 0); let _ = try!(writer.close()); @@ -275,8 +320,8 @@ impl AppHandler { debug!("Could not remove app from local config - app did not exist."); } - Ok(::observer::event_data::AppRemoval { - id : app_id, + Ok(AppRemoval { + id: app_id, result: None, }) } @@ -286,41 +331,41 @@ impl AppHandler { let reply = match self.on_modify_app_settings_impl(data) { Ok(data) => data, Err(err) => { - ::observer::event_data::AppModification { - id : id, + AppModification { + id: id, result: Err(err), } - }, + } }; group_send!(reply, &mut self.app_modify_observers); } fn on_modify_app_settings_impl(&mut self, - data: events::event_data::ModifyAppSettings) -> Result<::observer::event_data::AppModification, - ::errors::LauncherError> { + data: events::event_data::ModifyAppSettings) + -> Result { let (mut global_configs, config_dir) = try!(self.get_launcher_global_config_and_dir()); let mut global_config_modified = false; - let mut modification_detail = ::observer::event_data::ModificationDetail { - name : None, - local_path : None, + let mut modification_detail = ModificationDetail { + name: None, + local_path: None, safe_drive_access: None, }; { - let app_info = try!(global_configs.iter_mut().find(|config| config.app_id == data.id).ok_or(::errors::LauncherError::AppNotRegistered)); + let app_info = try!(global_configs.iter_mut() + .find(|config| config.app_id == data.id) + .ok_or(LauncherError::AppNotRegistered)); if let Some(safe_drive_access) = data.safe_drive_access { app_info.safe_drive_access = safe_drive_access; global_config_modified = true; - if self.ipc_server_event_sender.send(::launcher - ::ipc_server - ::events - ::ExternalEvent - ::ChangeSafeDriveAccess(data.id, safe_drive_access)).is_err() { + if self.ipc_server_event_sender + .send(ExternalEvent::ChangeSafeDriveAccess(data.id, safe_drive_access)) + .is_err() { debug!("Error asking IPC Server to change \"SAFEDrive\" permission for an app"); } @@ -335,11 +380,12 @@ impl AppHandler { } if global_config_modified { - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(self.client.clone()); + let file_helper = FileHelper::new(self.client.clone()); // TODO(to Krishna) -> can we change nfs to not require the following clone() ? - let file = unwrap_option!(config_dir.find_file(&::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string()) - .map(|file| file.clone()), "Logic Error - Report as bug."); - let mut writer = try!(file_helper.update_content(file, ::safe_nfs::helper::writer::Mode::Overwrite, config_dir)); + let file = unwrap_option!(config_dir.find_file( + &LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string()) + .map(|file| file.clone()), "Logic Error - Report as bug."); + let mut writer = try!(file_helper.update_content(file, Overwrite, config_dir)); writer.write(&try!(serialise(&global_configs)), 0); let _ = try!(writer.close()); } @@ -347,36 +393,38 @@ impl AppHandler { if let Some(new_path) = data.local_path { if let Some(prev_path) = self.local_config_data.insert(data.id, new_path.clone()) { - debug!("Replacing previous path {:?} for this app on this machine.", prev_path); + debug!("Replacing previous path {:?} for this app on this machine.", + prev_path); } modification_detail.local_path = Some(new_path); } - Ok(::observer::event_data::AppModification { - id : data.id, + Ok(AppModification { + id: data.id, result: Ok(modification_detail), }) } - fn on_register_app_add_observer(&mut self, observer: ::observer::AppHandlerObserver) { + fn on_register_app_add_observer(&mut self, observer: AppHandlerObserver) { self.app_add_observers.push(observer); } - fn on_register_app_remove_observer(&mut self, observer: ::observer::AppHandlerObserver) { + fn on_register_app_remove_observer(&mut self, observer: AppHandlerObserver) { self.app_remove_observers.push(observer); } - fn on_register_app_activate_observer(&mut self, observer: ::observer::AppHandlerObserver) { + fn on_register_app_activate_observer(&mut self, observer: AppHandlerObserver) { self.app_activate_observers.push(observer); } - fn on_register_app_modify_observer(&mut self, observer: ::observer::AppHandlerObserver) { + fn on_register_app_modify_observer(&mut self, observer: AppHandlerObserver) { self.app_modify_observers.push(observer); } - fn on_get_all_managed_apps(&self, observer: ::std::sync::mpsc::Sender, - ::errors::LauncherError>>) { + fn on_get_all_managed_apps(&self, + observer: mpsc::Sender, + LauncherError>>) { let global_configs = eval_send_one!(self.get_launcher_global_config(), &observer); let mut managed_apps = Vec::with_capacity(global_configs.len()); for it in global_configs.iter() { @@ -387,10 +435,10 @@ impl AppHandler { }; let managed_app = events::event_data::ManagedApp { - id : it.app_id, - name : it.app_name.clone(), - local_path : local_path, - reference_count : it.reference_count, + id: it.app_id, + name: it.app_name.clone(), + local_path: local_path, + reference_count: it.reference_count, safe_drive_access: it.safe_drive_access, }; @@ -398,7 +446,8 @@ impl AppHandler { } if let Err(err) = observer.send(Ok(managed_apps)) { - debug!("{:?} Error communicating all managed apps to observer.", err); + debug!("{:?} Error communicating all managed apps to observer.", + err); } } @@ -409,8 +458,7 @@ impl AppHandler { .collect() } - fn get_app_dir_name(app_name : &String, - directory_listing: &::safe_nfs::directory_listing::DirectoryListing) -> String { + fn get_app_dir_name(app_name: &String, directory_listing: &DirectoryListing) -> String { let mut dir_name = format!("{}-Root-Dir", &app_name); if directory_listing.find_sub_directory(&dir_name).is_some() { let mut index = 1u8; @@ -427,51 +475,66 @@ impl AppHandler { dir_name } - fn get_launcher_global_config(&self) -> Result, ::errors::LauncherError> { + fn get_launcher_global_config(&self) + -> Result, LauncherError> { Ok(try!(self.get_launcher_global_config_and_dir()).0) } - fn upsert_to_launcher_global_config(&self, config: misc::LauncherConfiguration) -> Result<(), ::errors::LauncherError> { + fn upsert_to_launcher_global_config(&self, + config: misc::LauncherConfiguration) + -> Result<(), LauncherError> { let (mut global_configs, dir_listing) = try!(self.get_launcher_global_config_and_dir()); // (Spandan) - // Due to bug in the language, unable to use `if let Some() .. else` logic to upsert to a vector. + // Unable to use `if let Some() .. else` logic to upsert to a vector due to a language bug. // Once the bug is resolved // - https://github.com/rust-lang/rust/issues/28449 // then modify the following to use it. - if let Some(pos) = global_configs.iter().position(|existing_config| existing_config.app_id == config.app_id) { - let existing_config = unwrap_option!(global_configs.get_mut(pos), "Logic Error - Report bug."); + if let Some(pos) = global_configs.iter().position(|existing_config| { + existing_config.app_id == config.app_id + }) { + let existing_config = unwrap_option!(global_configs.get_mut(pos), + "Logic Error - Report bug."); *existing_config = config; } else { global_configs.push(config); } let file = unwrap_option!(dir_listing.get_files() - .iter() - .find(|file| file.get_name() == ::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME), - "Logic Error - Launcher start-up should ensure the file must be present at this stage - Report bug.").clone(); - - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(self.client.clone()); - let mut writer = try!(file_helper.update_content(file, ::safe_nfs::helper::writer::Mode::Overwrite, dir_listing)); + .iter() + .find(|file| { + file.get_name() == LAUNCHER_GLOBAL_CONFIG_FILE_NAME + }), + "Logic Error - Launcher start-up should ensure the file must \ + be present at this stage - Report bug.") + .clone(); + + let file_helper = FileHelper::new(self.client.clone()); + let mut writer = try!(file_helper.update_content(file, Overwrite, dir_listing)); writer.write(&try!(serialise(&global_configs)), 0); let _ = try!(writer.close()); Ok(()) } - fn get_launcher_global_config_and_dir(&self) -> Result<(Vec, - ::safe_nfs::directory_listing::DirectoryListing), - ::errors::LauncherError> { - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(self.client.clone()); - let dir_listing = try!(dir_helper.get_configuration_directory_listing(::config::LAUNCHER_GLOBAL_DIRECTORY_NAME.to_string())); + fn get_launcher_global_config_and_dir + (&self) + -> Result<(Vec, DirectoryListing), LauncherError> { + let dir_helper = DirectoryHelper::new(self.client.clone()); + let dir_listing = try!(dir_helper.get_configuration_directory_listing( + LAUNCHER_GLOBAL_DIRECTORY_NAME.to_string())); let global_configs = { let file = unwrap_option!(dir_listing.get_files() - .iter() - .find(|file| file.get_name() == ::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME), - "Logic Error - Launcher start-up should ensure the file must be present at this stage - Report bug."); - - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(self.client.clone()); + .iter() + .find(|file| { + file.get_name() == + LAUNCHER_GLOBAL_CONFIG_FILE_NAME + }), + "Logic Error - Launcher start-up should ensure the file \ + must be present at this stage - Report bug."); + + let file_helper = FileHelper::new(self.client.clone()); let mut reader = file_helper.read(file); let size = reader.size(); @@ -489,8 +552,10 @@ impl AppHandler { impl Drop for AppHandler { fn drop(&mut self) { - let plain_text = unwrap_result!(serialise(&misc::convert_hashmap_to_vec(&self.local_config_data))); - let cipher_text = unwrap_result!(unwrap_result!(self.client.lock()).hybrid_encrypt(&plain_text, None)); + let plain_text = + unwrap_result!(serialise(&misc::convert_hashmap_to_vec(&self.local_config_data))); + let cipher_text = unwrap_result!(unwrap_result!(self.client.lock()) + .hybrid_encrypt(&plain_text, None)); unwrap_result!(misc::flush_to_local_config(&cipher_text)); } } diff --git a/src/launcher/ipc_server/events.rs b/src/launcher/ipc_server/events.rs index fe06d2ec..4ac5f9fb 100644 --- a/src/launcher/ipc_server/events.rs +++ b/src/launcher/ipc_server/events.rs @@ -15,6 +15,12 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::fmt; +use std::net::TcpStream; +use std::sync::mpsc; + +use errors::LauncherError; +use observer::IpcObserver; use xor_name::XorName; #[derive(Clone, Debug)] @@ -28,8 +34,8 @@ pub enum IpcServerEventCategory { #[derive(Debug)] pub enum IpcListenerEvent { - IpcListenerAborted(Box<::errors::LauncherError>), - SpawnIpcSession(::std::net::TcpStream), + IpcListenerAborted(Box), + SpawnIpcSession(TcpStream), } // -------------------------------------------------------------------------------------- @@ -60,22 +66,22 @@ pub enum ExternalEvent { #[doc(hidden)] ChangeSafeDriveAccess(XorName, bool), /// Obtain the endpoint on which the Launcher IPC is listening to for incoming connections. - GetListenerEndpoint(::std::sync::mpsc::Sender), + GetListenerEndpoint(mpsc::Sender), /// Request IPC Server to forget a session with given app-id. The session will be terminated. EndSession(XorName), /// Register an observer to receive notifications about changes in verified sessions. - RegisterVerifiedSessionObserver(::observer::IpcObserver), + RegisterVerifiedSessionObserver(IpcObserver), /// Register an observer to receive notifications about changes in unverified sessions. - RegisterUnverifiedSessionObserver(::observer::IpcObserver), + RegisterUnverifiedSessionObserver(IpcObserver), /// Register an observer to receive notifications about changes in pending verifications. - RegisterPendingVerificationObserver(::observer::IpcObserver), + RegisterPendingVerificationObserver(IpcObserver), /// Terminate Launcher IPC - this will essentially exit all sessions and close IPC down /// gracefully. Terminate, } -impl ::std::fmt::Debug for ExternalEvent { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl fmt::Debug for ExternalEvent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let ExternalEvent::GetListenerEndpoint(_) = *self { write!(f, "ExternalEvent::GetListenerEndpoint") } else { @@ -94,18 +100,19 @@ impl From for ExternalEvent { pub mod event_data { use xor_name::XorName; + use safe_nfs::metadata::directory_key::DirectoryKey; #[derive(Debug, Clone)] pub struct ActivationDetail { - pub nonce : String, - pub app_id : XorName, - pub app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, + pub nonce: String, + pub app_id: XorName, + pub app_root_dir_key: DirectoryKey, pub safe_drive_access: bool, } #[derive(Debug)] pub struct SessionTerminationDetail { - pub id : SessionId, + pub id: SessionId, pub reason: ::errors::LauncherError, } diff --git a/src/launcher/ipc_server/ipc_session/authenticate_app.rs b/src/launcher/ipc_server/ipc_session/authenticate_app.rs index a837c165..8d7cc32b 100644 --- a/src/launcher/ipc_server/ipc_session/authenticate_app.rs +++ b/src/launcher/ipc_server/ipc_session/authenticate_app.rs @@ -16,42 +16,63 @@ // relating to use of the SAFE Network Software. use maidsafe_utilities::thread::RaiiThreadJoiner; +use launcher::ipc_server::ipc_session; const NONCE_VERIFIER_THREAD_NAME: &'static str = "LauncherNonceVerifierThread"; const APP_AUTHENTICATION_ENDPOINT: &'static str = "safe-api/v1.0/handshake/authenticate-app"; -pub fn verify_launcher_nonce(mut ipc_stream : ::launcher::ipc_server::ipc_session::stream::IpcStream, - event_sender : ::launcher::ipc_server::ipc_session - ::EventSenderToSession<::launcher::ipc_server::ipc_session - ::events::AppAuthenticationEvent>) -> RaiiThreadJoiner { +pub fn verify_launcher_nonce( + mut ipc_stream : ipc_session::stream::IpcStream, + event_sender : ipc_session::EventSenderToSession< + ipc_session::events::AppAuthenticationEvent>) + -> RaiiThreadJoiner { let joiner = thread!(NONCE_VERIFIER_THREAD_NAME, move || { use rustc_serialize::base64::FromBase64; + use rustc_serialize::json; + use sodiumoxide::crypto::box_; + use errors::LauncherError; + use launcher::ipc_server::ipc_session::events::event_data::AuthData; let payload = eval_send_one!(ipc_stream.read_payload(), &event_sender); - let payload_as_str = eval_send_one!(parse_result!(String::from_utf8(payload), "Invalid UTF-8"), &event_sender); - let handshake_request: HandshakeRequest = eval_send_one!(::rustc_serialize::json::decode(&payload_as_str), &event_sender); + let payload_as_str = eval_send_one!(parse_result!(String::from_utf8(payload), + "Invalid UTF-8"), + &event_sender); + let handshake_request: HandshakeRequest = eval_send_one!(json::decode(&payload_as_str), + &event_sender); if handshake_request.endpoint != APP_AUTHENTICATION_ENDPOINT { - eval_send_one!(Err(::errors::LauncherError::SpecificParseError("Invalid endpoint for app-auhtentication".to_string())), + eval_send_one!(Err(LauncherError::SpecificParseError("Invalid endpoint for \ + app-auhtentication" + .to_string())), &event_sender); } - let vec_nonce = eval_send_one!(parse_result!(handshake_request.data.asymm_nonce.from_base64(), "Nonce -> Base64"), + let vec_nonce = eval_send_one!(parse_result!(handshake_request.data + .asymm_nonce + .from_base64(), + "Nonce -> Base64"), &event_sender); - if vec_nonce.len() != ::sodiumoxide::crypto::box_::NONCEBYTES { - eval_send_one!(Err(::errors::LauncherError::SpecificParseError("Invalid asymmetric nonce length.".to_string())), + if vec_nonce.len() != box_::NONCEBYTES { + eval_send_one!(Err(LauncherError::SpecificParseError("Invalid asymmetric nonce \ + length." + .to_string())), &event_sender); } - let vec_pub_key = eval_send_one!(parse_result!(handshake_request.data.asymm_pub_key.from_base64(), "PublicKey -> Base64"), - &event_sender); - if vec_pub_key.len() != ::sodiumoxide::crypto::box_::PUBLICKEYBYTES { - eval_send_one!(Err(::errors::LauncherError::SpecificParseError("Invalid asymmetric public key length.".to_string())), + let vec_pub_key = eval_send_one!(parse_result!(handshake_request.data + .asymm_pub_key + .from_base64(), + "PublicKey -> Base64"), + &event_sender); + if vec_pub_key.len() != box_::PUBLICKEYBYTES { + eval_send_one!(Err(LauncherError::SpecificParseError("Invalid asymmetric public \ + key length." + .to_string())), &event_sender); } - let mut asymm_nonce = ::sodiumoxide::crypto::box_::Nonce([0; ::sodiumoxide::crypto::box_::NONCEBYTES]); - let mut asymm_pub_key = ::sodiumoxide::crypto::box_::PublicKey([0; ::sodiumoxide::crypto::box_::PUBLICKEYBYTES]); + let mut asymm_nonce = box_::Nonce([0; box_::NONCEBYTES]); + let mut asymm_pub_key = box_::PublicKey([0; box_::PUBLICKEYBYTES]); for it in vec_nonce.into_iter().enumerate() { asymm_nonce.0[it.0] = it.1; @@ -60,11 +81,12 @@ pub fn verify_launcher_nonce(mut ipc_stream : ::launcher::ipc_server::ipc_sessi asymm_pub_key.0[it.0] = it.1; } - if let Err(err) = send_one!(Ok(::launcher::ipc_server::ipc_session::events::event_data::AuthData { - str_nonce : handshake_request.data.launcher_string, - asymm_nonce : asymm_nonce, - asymm_pub_key: asymm_pub_key, - }), &event_sender) { + if let Err(err) = send_one!(Ok(AuthData { + str_nonce: handshake_request.data.launcher_string, + asymm_nonce: asymm_nonce, + asymm_pub_key: asymm_pub_key, + }), + &event_sender) { debug!("{:?} Error sending authentication data to IPCSession.", err); } @@ -76,13 +98,13 @@ pub fn verify_launcher_nonce(mut ipc_stream : ::launcher::ipc_server::ipc_sessi #[derive(RustcDecodable, Debug)] struct HandshakeRequest { - data : HandshakeData, + data: HandshakeData, endpoint: String, } #[derive(RustcDecodable, Debug)] struct HandshakeData { - asymm_nonce : String, - asymm_pub_key : String, + asymm_nonce: String, + asymm_pub_key: String, launcher_string: String, } diff --git a/src/launcher/ipc_server/ipc_session/ecdh_key_exchange.rs b/src/launcher/ipc_server/ipc_session/ecdh_key_exchange.rs index fc107d96..c4b0eb75 100644 --- a/src/launcher/ipc_server/ipc_session/ecdh_key_exchange.rs +++ b/src/launcher/ipc_server/ipc_session/ecdh_key_exchange.rs @@ -15,40 +15,45 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. -pub fn perform_ecdh_exchange(ipc_stream : &mut ::launcher::ipc_server::ipc_session::stream::IpcStream, - app_nonce : ::sodiumoxide::crypto::box_::Nonce, - app_pub_key: ::sodiumoxide::crypto::box_::PublicKey) -> Result<(::sodiumoxide::crypto::secretbox::Nonce, - ::sodiumoxide::crypto::secretbox::Key), - ::errors::LauncherError> { - use ::rustc_serialize::base64::ToBase64; +use sodiumoxide::crypto::{box_, secretbox}; - let key = ::sodiumoxide::crypto::secretbox::gen_key(); - let nonce = ::sodiumoxide::crypto::secretbox::gen_nonce(); +use errors::LauncherError; +use launcher::ipc_server::ipc_session::stream::IpcStream; - let (launcher_public_key, launcher_secret_key) = ::sodiumoxide::crypto::box_::gen_keypair(); +pub fn perform_ecdh_exchange(ipc_stream: &mut IpcStream, + app_nonce: box_::Nonce, + app_pub_key: box_::PublicKey) + -> Result<(secretbox::Nonce, secretbox::Key), LauncherError> { + use rustc_serialize::base64::ToBase64; + use rustc_serialize::json; - let mut data = [0u8; ::sodiumoxide::crypto::secretbox::NONCEBYTES + ::sodiumoxide::crypto::secretbox::KEYBYTES]; + let key = secretbox::gen_key(); + let nonce = secretbox::gen_nonce(); + + let (launcher_public_key, launcher_secret_key) = box_::gen_keypair(); + + let mut data = [0u8; secretbox::NONCEBYTES + secretbox::KEYBYTES]; for (i, item) in nonce.0.iter().chain(key.0.iter()).enumerate() { - data[i] = *item; + data[i] = *item; } - let cipher_text = ::sodiumoxide::crypto::box_::seal(&data, &app_nonce, &app_pub_key, &launcher_secret_key); + let cipher_text = box_::seal(&data, &app_nonce, &app_pub_key, &launcher_secret_key); let b64_config = ::config::get_base64_config(); let launcher_pub_key_base64 = launcher_public_key.0.to_base64(b64_config); let cipher_text_base64 = cipher_text.to_base64(b64_config); let response = EcdhKeyExchgResponse { - encrypted_symm_key : cipher_text_base64, - launcher_public_key: launcher_pub_key_base64, + encrypted_symm_key: cipher_text_base64, + launcher_public_key: launcher_pub_key_base64, }; let json_packet = JsonPacket { - id : String::new(), - data: response, + id: String::new(), + data: response, }; - let payload = try!(::rustc_serialize::json::encode(&json_packet)); + let payload = try!(json::encode(&json_packet)); try!(ipc_stream.write(payload.into_bytes())); @@ -57,12 +62,12 @@ pub fn perform_ecdh_exchange(ipc_stream : &mut ::launcher::ipc_server::ipc_sessi #[derive(RustcEncodable, Debug)] struct JsonPacket { - pub id : String, + pub id: String, pub data: EcdhKeyExchgResponse, } #[derive(RustcEncodable, Debug)] struct EcdhKeyExchgResponse { - pub encrypted_symm_key : String, + pub encrypted_symm_key: String, pub launcher_public_key: String, } diff --git a/src/launcher/ipc_server/ipc_session/events.rs b/src/launcher/ipc_server/ipc_session/events.rs index dd5d8192..f86ff481 100644 --- a/src/launcher/ipc_server/ipc_session/events.rs +++ b/src/launcher/ipc_server/ipc_session/events.rs @@ -15,20 +15,22 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; + #[derive(Clone, Debug)] pub enum IpcSessionEventCategory { - AppAuthenticationEvent, + AppAuthenticationEvent, SecureCommunicationEvent, ExternalEvent, } // -------------------------------------------------------------------------------------- -pub type AppAuthenticationEvent = Result; +pub type AppAuthenticationEvent = Result; // -------------------------------------------------------------------------------------- -pub type SecureCommunicationEvent = Result<(), ::errors::LauncherError>; +pub type SecureCommunicationEvent = Result<(), LauncherError>; // -------------------------------------------------------------------------------------- @@ -50,25 +52,32 @@ impl From for ExternalEvent { pub mod event_data { use xor_name::XorName; + use std::fmt; + use std::sync::{Arc, Mutex}; + use safe_core::client::Client; + use safe_nfs::metadata::directory_key::DirectoryKey; pub struct AppDetail { - pub client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - pub app_id : XorName, - pub app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, + pub client: Arc>, + pub app_id: XorName, + pub app_root_dir_key: DirectoryKey, pub safe_drive_access: bool, } - impl ::std::fmt::Debug for AppDetail { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "AppDetail {{ client: Arc>, app_id: {:?}, safe_drive_access: {:?}, }}", - self.app_id, self.safe_drive_access) + impl fmt::Debug for AppDetail { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, + "AppDetail {{ client: Arc>, app_id: {:?}, safe_drive_access: \ + {:?}, }}", + self.app_id, + self.safe_drive_access) } } #[derive(Debug)] pub struct AuthData { - pub str_nonce : String, - pub asymm_nonce : ::sodiumoxide::crypto::box_::Nonce, + pub str_nonce: String, + pub asymm_nonce: ::sodiumoxide::crypto::box_::Nonce, pub asymm_pub_key: ::sodiumoxide::crypto::box_::PublicKey, } } diff --git a/src/launcher/ipc_server/ipc_session/mod.rs b/src/launcher/ipc_server/ipc_session/mod.rs index dac04da4..0b509a3c 100644 --- a/src/launcher/ipc_server/ipc_session/mod.rs +++ b/src/launcher/ipc_server/ipc_session/mod.rs @@ -15,13 +15,24 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::net::{Shutdown, TcpStream}; +use std::sync::{Arc, mpsc, Mutex}; + +use sodiumoxide::crypto::box_; + +use errors::LauncherError; use xor_name::XorName; use maidsafe_utilities::thread::RaiiThreadJoiner; use maidsafe_utilities::event_sender::EventSender; +use launcher::ipc_server::EventSenderToServer; +use launcher::ipc_server::events::IpcSessionEvent; +use launcher::ipc_server::events::event_data::{SessionId, SessionTerminationDetail}; + pub mod events; -pub type EventSenderToSession = EventSender; +pub type EventSenderToSession = EventSender; mod stream; mod authenticate_app; @@ -31,59 +42,61 @@ mod secure_communication; const IPC_SESSION_THREAD_NAME: &'static str = "IpcSessionThread"; pub struct IpcSession { - app_id : Option, - temp_id : u32, - stream : ::std::net::TcpStream, - app_nonce : Option<::sodiumoxide::crypto::box_::Nonce>, - app_pub_key : Option<::sodiumoxide::crypto::box_::PublicKey>, - raii_joiner : RaiiThreadJoiner, - safe_drive_access : Option<::std::sync::Arc<::std::sync::Mutex>>, // TODO(Spandan) change to 3-level permission instead of 2 - event_catagory_tx : ::std::sync::mpsc::Sender, - external_event_rx : ::std::sync::mpsc::Receiver, - secure_comm_event_rx : ::std::sync::mpsc::Receiver, - secure_comm_event_tx : ::std::sync::mpsc::Sender, - authentication_event_rx: ::std::sync::mpsc::Receiver, - ipc_server_event_sender: ::launcher::ipc_server::EventSenderToServer<::launcher::ipc_server::events::IpcSessionEvent>, + app_id: Option, + temp_id: u32, + stream: TcpStream, + app_nonce: Option, + app_pub_key: Option, + raii_joiner: RaiiThreadJoiner, + // TODO(Spandan) change to 3-level permission instead of 2 + safe_drive_access: Option>>, + event_catagory_tx: mpsc::Sender, + external_event_rx: mpsc::Receiver, + secure_comm_event_rx: mpsc::Receiver, + secure_comm_event_tx: mpsc::Sender, + authentication_event_rx: mpsc::Receiver, + ipc_server_event_sender: EventSenderToServer, } impl IpcSession { - pub fn new(server_event_sender: ::launcher::ipc_server::EventSenderToServer<::launcher::ipc_server::events::IpcSessionEvent>, - temp_id : u32, - stream : ::std::net::TcpStream) -> Result<(RaiiThreadJoiner, - EventSenderToSession), - ::errors::LauncherError> { - let ipc_stream = try!(stream::IpcStream::new(try!(stream.try_clone() - .map_err(|err| ::errors - ::LauncherError - ::IpcStreamCloneError(err))))); - - let (event_catagory_tx, event_catagory_rx) = ::std::sync::mpsc::channel(); - let (external_event_tx, external_event_rx) = ::std::sync::mpsc::channel(); - let (secure_comm_event_tx, secure_comm_event_rx) = ::std::sync::mpsc::channel(); - let (authentication_event_tx, authentication_event_rx) = ::std::sync::mpsc::channel(); + pub fn new(server_event_sender: EventSenderToServer, + temp_id: u32, + stream: TcpStream) + -> Result<(RaiiThreadJoiner, + EventSenderToSession), + LauncherError> { + let ipc_stream = try!(stream::IpcStream::new(try!(stream.try_clone().map_err(|err| { + LauncherError::IpcStreamCloneError(err) + })))); + + let (event_catagory_tx, event_catagory_rx) = mpsc::channel(); + let (external_event_tx, external_event_rx) = mpsc::channel(); + let (secure_comm_event_tx, secure_comm_event_rx) = mpsc::channel(); + let (authentication_event_tx, authentication_event_rx) = mpsc::channel(); let cloned_event_catagory_tx = event_catagory_tx.clone(); let ipc_session_joiner = thread!(IPC_SESSION_THREAD_NAME, move || { let authentication_event_sender = EventSenderToSession:: - ::new(authentication_event_tx, - events::IpcSessionEventCategory::AppAuthenticationEvent, - cloned_event_catagory_tx.clone()); + ::new(authentication_event_tx, + events::IpcSessionEventCategory::AppAuthenticationEvent, + cloned_event_catagory_tx.clone()); - let joiner = authenticate_app::verify_launcher_nonce(ipc_stream, authentication_event_sender); + let joiner = authenticate_app::verify_launcher_nonce(ipc_stream, + authentication_event_sender); let mut ipc_session = IpcSession { - app_id : None, - temp_id : temp_id, - stream : stream, - app_nonce : None, - app_pub_key : None, - raii_joiner : joiner, - safe_drive_access : None, - event_catagory_tx : cloned_event_catagory_tx, - external_event_rx : external_event_rx, - secure_comm_event_rx : secure_comm_event_rx, - secure_comm_event_tx : secure_comm_event_tx, + app_id: None, + temp_id: temp_id, + stream: stream, + app_nonce: None, + app_pub_key: None, + raii_joiner: joiner, + safe_drive_access: None, + event_catagory_tx: cloned_event_catagory_tx, + external_event_rx: external_event_rx, + secure_comm_event_rx: secure_comm_event_rx, + secure_comm_event_tx: secure_comm_event_tx, authentication_event_rx: authentication_event_rx, ipc_server_event_sender: server_event_sender, }; @@ -94,41 +107,46 @@ impl IpcSession { }); let external_event_sender = EventSenderToSession:: - ::new(external_event_tx, - events::IpcSessionEventCategory::ExternalEvent, - event_catagory_tx); + ::new(external_event_tx, + events::IpcSessionEventCategory::ExternalEvent, + event_catagory_tx); - Ok((RaiiThreadJoiner::new(ipc_session_joiner), external_event_sender)) + Ok((RaiiThreadJoiner::new(ipc_session_joiner), + external_event_sender)) } - fn run(&mut self, event_catagory_rx: ::std::sync::mpsc::Receiver) { + fn run(&mut self, event_catagory_rx: mpsc::Receiver) { for event_category in event_catagory_rx.iter() { match event_category { events::IpcSessionEventCategory::AppAuthenticationEvent => { if let Ok(authentication_event) = self.authentication_event_rx.try_recv() { match authentication_event { Ok(auth_data) => self.on_auth_data_received(auth_data), - Err(err) => self.terminate_session(err), + Err(err) => self.terminate_session(err), } } - }, + } events::IpcSessionEventCategory::SecureCommunicationEvent => { if let Ok(secure_comm_event) = self.secure_comm_event_rx.try_recv() { match secure_comm_event { - Ok(()) => (), + Ok(()) => (), Err(err) => self.terminate_session(err), } } - }, + } events::IpcSessionEventCategory::ExternalEvent => { if let Ok(external_event) = self.external_event_rx.try_recv() { match external_event { - events::ExternalEvent::AppDetailReceived(app_detail) => self.on_app_detail_received(app_detail), - events::ExternalEvent::ChangeSafeDriveAccess(is_allowed) => self.on_change_safe_drive_access(is_allowed), + events::ExternalEvent::AppDetailReceived(app_detail) => { + self.on_app_detail_received(app_detail) + } + events::ExternalEvent::ChangeSafeDriveAccess(is_allowed) => { + self.on_change_safe_drive_access(is_allowed) + } events::ExternalEvent::Terminate => break, } } - }, + } } } } @@ -137,19 +155,24 @@ impl IpcSession { self.app_nonce = Some(auth_data.asymm_nonce); self.app_pub_key = Some(auth_data.asymm_pub_key); - let _ = send_one!((self.temp_id, auth_data.str_nonce), &self.ipc_server_event_sender); + let _ = send_one!((self.temp_id, auth_data.str_nonce), + &self.ipc_server_event_sender); } fn on_app_detail_received(&mut self, app_detail: Box) { let app_detail = *app_detail; self.app_id = Some(app_detail.app_id); - self.safe_drive_access = Some(::std::sync::Arc::new(::std::sync::Mutex::new(app_detail.safe_drive_access))); + self.safe_drive_access = Some(Arc::new(Mutex::new(app_detail.safe_drive_access))); if let Some(mut ipc_stream) = self.get_ipc_stream_or_terminate() { match ecdh_key_exchange::perform_ecdh_exchange(&mut ipc_stream, - unwrap_option!(self.app_nonce, "Logic Error - Report a bug."), - unwrap_option!(self.app_pub_key, "Logice Error - Report a bug.")) { + unwrap_option!(self.app_nonce, + "Logic Error - \ + Report a bug."), + unwrap_option!(self.app_pub_key, + "Logice Error - \ + Report a bug.")) { Ok((symm_nonce, symm_key)) => { let safe_drive_access = if let Some(ref access) = self.safe_drive_access { access.clone() @@ -158,22 +181,23 @@ impl IpcSession { }; let event_sender = EventSenderToSession:: - ::new(self.secure_comm_event_tx.clone(), - events::IpcSessionEventCategory::SecureCommunicationEvent, - self.event_catagory_tx.clone()); - - self.raii_joiner = secure_communication::SecureCommunication::new(app_detail.client, - event_sender, - symm_key, - symm_nonce, - ipc_stream, - app_detail.app_root_dir_key, - safe_drive_access); - }, + ::new(self.secure_comm_event_tx.clone(), + events::IpcSessionEventCategory::SecureCommunicationEvent, + self.event_catagory_tx.clone()); + + self.raii_joiner = + secure_communication::SecureCommunication::new(app_detail.client, + event_sender, + symm_key, + symm_nonce, + ipc_stream, + app_detail.app_root_dir_key, + safe_drive_access); + } Err(err) => { debug!("ECDH Key Exchange unsuccessful {:?}", err); self.terminate_session(err); - }, + } } } } @@ -190,19 +214,19 @@ impl IpcSession { Err(err) => { self.terminate_session(err); None - }, + } } } - fn terminate_session(&self, reason: ::errors::LauncherError) { + fn terminate_session(&self, reason: LauncherError) { let id = if let Some(ref app_id) = self.app_id { - ::launcher::ipc_server::events::event_data::SessionId::AppId(Box::new(app_id.clone())) + SessionId::AppId(Box::new(app_id.clone())) } else { - ::launcher::ipc_server::events::event_data::SessionId::TempId(self.temp_id) + SessionId::TempId(self.temp_id) }; - let termination_detail = ::launcher::ipc_server::events::event_data::SessionTerminationDetail { - id : id, + let termination_detail = SessionTerminationDetail { + id: id, reason: reason, }; @@ -211,25 +235,29 @@ impl IpcSession { } } - fn get_ipc_stream(&self) -> Result { - let stream = try!(self.stream.try_clone().map_err(|err| ::errors - ::LauncherError - ::IpcStreamCloneError(err))); + fn get_ipc_stream(&self) -> Result { + let stream = try!(self.stream + .try_clone() + .map_err(|err| LauncherError::IpcStreamCloneError(err))); stream::IpcStream::new(stream) } } impl Drop for IpcSession { fn drop(&mut self) { - if let Err(err) = self.stream.shutdown(::std::net::Shutdown::Both) { + if let Err(err) = self.stream.shutdown(Shutdown::Both) { debug!("Failed to gracefully shutdown session for app-id {:?} with error {:?}", - self.app_id, err); + self.app_id, + err); } } } #[cfg(test)] mod tests { + use std::collections::BTreeMap; + use rustc_serialize::json; + use sodiumoxide::crypto::box_; use xor_name::XorName; use maidsafe_utilities::thread::RaiiThreadJoiner; @@ -242,101 +270,105 @@ mod tests { #[derive(Debug)] struct HandshakePayload { pub launcher_string: String, - pub nonce: [u8; ::sodiumoxide::crypto::box_::NONCEBYTES], - pub public_encryption_key: [u8; ::sodiumoxide::crypto::box_::PUBLICKEYBYTES], + pub nonce: [u8; box_::NONCEBYTES], + pub public_encryption_key: [u8; box_::PUBLICKEYBYTES], } - impl ::rustc_serialize::json::ToJson for HandshakePayload { - fn to_json(&self) -> ::rustc_serialize::json::Json { - use ::rustc_serialize::base64::ToBase64; + impl json::ToJson for HandshakePayload { + fn to_json(&self) -> json::Json { + use rustc_serialize::base64::ToBase64; - let mut tree = ::std::collections::BTreeMap::new(); + let mut tree = BTreeMap::new(); let config = ::config::get_base64_config(); let base64_nonce = (&self.nonce).to_base64(config); let base64_pub_encryption_key = (&self.public_encryption_key).to_base64(config); - assert!(tree.insert("launcher_string".to_string(), self.launcher_string.to_json()).is_none()); + assert!(tree.insert("launcher_string".to_string(), + self.launcher_string.to_json()) + .is_none()); assert!(tree.insert("asymm_nonce".to_string(), base64_nonce.to_json()).is_none()); - assert!(tree.insert("asymm_pub_key".to_string(), base64_pub_encryption_key.to_json()).is_none()); + assert!(tree.insert("asymm_pub_key".to_string(), + base64_pub_encryption_key.to_json()) + .is_none()); - ::rustc_serialize::json::Json::Object(tree) + json::Json::Object(tree) } } - impl ::rustc_serialize::json::ToJson for HandshakeRequest { - fn to_json(&self) -> ::rustc_serialize::json::Json { - let mut tree = ::std::collections::BTreeMap::new(); + impl json::ToJson for HandshakeRequest { + fn to_json(&self) -> json::Json { + let mut tree = BTreeMap::new(); assert!(tree.insert("endpoint".to_string(), self.endpoint.to_json()).is_none()); assert!(tree.insert("data".to_string(), self.data.to_json()).is_none()); - ::rustc_serialize::json::Json::Object(tree) + json::Json::Object(tree) } } #[test] fn application_handshake() { - use ::rustc_serialize::json::ToJson; + use std::sync::{Arc, mpsc, Mutex}; + use rustc_serialize::json::ToJson; + use safe_core::utility; + use safe_nfs::AccessLevel; + use launcher::ipc_server::IpcServer; + use launcher::ipc_server::events::ExternalEvent; + use launcher::ipc_server::events::event_data::ActivationDetail; + use launcher::ipc_server::ipc_session::stream::IpcStream; - let client = ::std - ::sync - ::Arc::new(::std - ::sync - ::Mutex::new(unwrap_result!(::safe_core::utility::test_utils::get_client()))); + let client = Arc::new(Mutex::new(unwrap_result!(utility::test_utils::get_client()))); - let (_raii_joiner_0, event_sender) = unwrap_result!(::launcher::ipc_server::IpcServer::new(client)); + let (_raii_joiner_0, event_sender) = unwrap_result!(IpcServer::new(client)); - let (tx, rx) = ::std::sync::mpsc::channel(); - unwrap_result!(event_sender.send(::launcher::ipc_server::events::ExternalEvent::GetListenerEndpoint(tx))); + let (tx, rx) = mpsc::channel(); + unwrap_result!(event_sender.send(ExternalEvent::GetListenerEndpoint(tx))); let listener_ep = unwrap_result!(rx.recv()); - let app_id = XorName(unwrap_result!(::safe_core::utility::generate_random_array_u8_64())); - let dir_id = XorName(unwrap_result!(::safe_core::utility::generate_random_array_u8_64())); - let directory_key = ::safe_nfs::metadata::directory_key::DirectoryKey::new(dir_id, - 10u64, - false, - ::safe_nfs::AccessLevel::Private); - let activation_details = ::launcher::ipc_server::events::event_data::ActivationDetail { - nonce : "mock_nonce_string".to_string(), - app_id : app_id, - app_root_dir_key : directory_key, + let app_id = XorName(unwrap_result!(utility::generate_random_array_u8_64())); + let dir_id = XorName(unwrap_result!(utility::generate_random_array_u8_64())); + let directory_key = + ::safe_nfs::metadata::directory_key::DirectoryKey::new(dir_id, + 10u64, + false, + AccessLevel::Private); + let activation_details = ActivationDetail { + nonce: "mock_nonce_string".to_string(), + app_id: app_id, + app_root_dir_key: directory_key, safe_drive_access: false, }; - let activate_event = ::launcher::ipc_server::events::ExternalEvent::AppActivated(Box::new(activation_details)); + let activate_event = ExternalEvent::AppActivated(Box::new(activation_details)); unwrap_result!(event_sender.send(activate_event)); let stream = unwrap_result!(::std::net::TcpStream::connect(&listener_ep[..])); let _raii_joiner_1 = RaiiThreadJoiner::new(thread!("AppHandshakeThread", move || { - let mut ipc_stream = unwrap_result!(::launcher - ::ipc_server - ::ipc_session - ::stream - ::IpcStream::new(stream)); - let app_nonce = ::sodiumoxide::crypto::box_::gen_nonce(); - let (app_public_key, _) = ::sodiumoxide::crypto::box_::gen_keypair(); - let payload = HandshakePayload { - launcher_string : "mock_nonce_string".to_string(), - nonce : app_nonce.0, - public_encryption_key: app_public_key.0, - }; - let request = HandshakeRequest { - endpoint: "safe-api/v1.0/handshake/authenticate-app".to_string(), - data : payload, - }; - - let json_obj = request.to_json(); - unwrap_result!(ipc_stream.write(json_obj.to_string().into_bytes())); - - // TODO(Krishna) -> use response - let _response = unwrap_result!(ipc_stream.read_payload()); - assert!(ipc_stream.read_payload().is_err()) + let mut ipc_stream = unwrap_result!(IpcStream::new(stream)); + let app_nonce = box_::gen_nonce(); + let (app_public_key, _) = box_::gen_keypair(); + let payload = HandshakePayload { + launcher_string: "mock_nonce_string".to_string(), + nonce: app_nonce.0, + public_encryption_key: app_public_key.0, + }; + let request = HandshakeRequest { + endpoint: "safe-api/v1.0/handshake/authenticate-app".to_string(), + data: payload, + }; + + let json_obj = request.to_json(); + unwrap_result!(ipc_stream.write(json_obj.to_string().into_bytes())); + + // TODO(Krishna) -> use response + let _response = unwrap_result!(ipc_stream.read_payload()); + assert!(ipc_stream.read_payload().is_err()) })); let duration = ::std::time::Duration::from_millis(3000); ::std::thread::sleep(duration); - unwrap_result!(event_sender.send(::launcher::ipc_server::events::ExternalEvent::Terminate)); + unwrap_result!(event_sender.send(ExternalEvent::Terminate)); } } diff --git a/src/launcher/ipc_server/ipc_session/secure_communication.rs b/src/launcher/ipc_server/ipc_session/secure_communication.rs index 89ce3028..0ff3b037 100644 --- a/src/launcher/ipc_server/ipc_session/secure_communication.rs +++ b/src/launcher/ipc_server/ipc_session/secure_communication.rs @@ -15,53 +15,63 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::sync::{Arc, Mutex}; + +use rustc_serialize::json; +use sodiumoxide::crypto::secretbox; + use maidsafe_utilities::thread::RaiiThreadJoiner; +use errors::LauncherError; +use launcher::ipc_server::ipc_session; +use launcher::parser; +use safe_core::client::Client; +use safe_nfs::metadata::directory_key::DirectoryKey; +use safe_nfs::helper::directory_helper::DirectoryHelper; const SECURE_COMM_THREAD_NAME: &'static str = "SecureCommunicationThread"; pub struct SecureCommunication { - observer : ::launcher::ipc_server::ipc_session::EventSenderToSession<::launcher - ::ipc_server - ::ipc_session - ::events::SecureCommunicationEvent>, - symm_key : ::sodiumoxide::crypto::secretbox::Key, - symm_nonce : ::sodiumoxide::crypto::secretbox::Nonce, - ipc_stream : ::launcher::ipc_server::ipc_session::stream::IpcStream, - parser_parameters: ::launcher::parser::ParameterPacket, + observer: ipc_session::EventSenderToSession, + symm_key: secretbox::Key, + symm_nonce: secretbox::Nonce, + ipc_stream: ipc_session::stream::IpcStream, + parser_parameters: parser::ParameterPacket, } impl SecureCommunication { - pub fn new(client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - observer : ::launcher::ipc_server::ipc_session::EventSenderToSession<::launcher - ::ipc_server - ::ipc_session - ::events::SecureCommunicationEvent>, - symm_key : ::sodiumoxide::crypto::secretbox::Key, - symm_nonce : ::sodiumoxide::crypto::secretbox::Nonce, - ipc_stream : ::launcher::ipc_server::ipc_session::stream::IpcStream, - app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, - safe_drive_access: ::std::sync::Arc<::std::sync::Mutex>) -> RaiiThreadJoiner { + pub fn new(client : Arc<::std::sync::Mutex>, + observer : ipc_session::EventSenderToSession< + ipc_session::events::SecureCommunicationEvent>, + symm_key : secretbox::Key, + symm_nonce : secretbox::Nonce, + ipc_stream : ipc_session::stream::IpcStream, + app_root_dir_key : DirectoryKey, + safe_drive_access: Arc>) -> RaiiThreadJoiner { let joiner = thread!(SECURE_COMM_THREAD_NAME, move || { let safe_drive_dir_key = { - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(client.clone()); - let user_root_dir_listing = eval_send_one!(dir_helper.get_user_root_directory_listing(), &observer); - eval_send_one!(user_root_dir_listing.find_sub_directory(&::config::SAFE_DRIVE_DIR_NAME.to_string()) - .ok_or(::errors::LauncherError::from("Could not find SAFEDrive")), - &observer).get_key().clone() + let dir_helper = DirectoryHelper::new(client.clone()); + let user_root_dir_listing = + eval_send_one!(dir_helper.get_user_root_directory_listing(), &observer); + eval_send_one!(user_root_dir_listing.find_sub_directory( + &::config::SAFE_DRIVE_DIR_NAME.to_string()).ok_or( + LauncherError::from("Could not find SAFEDrive")), + &observer) + .get_key() + .clone() }; - let parameter_packet = ::launcher::parser::ParameterPacket { - client : client, - app_root_dir_key : app_root_dir_key, - safe_drive_access : safe_drive_access, + let parameter_packet = parser::ParameterPacket { + client: client, + app_root_dir_key: app_root_dir_key, + safe_drive_access: safe_drive_access, safe_drive_dir_key: safe_drive_dir_key, }; let mut secure_comm_obj = SecureCommunication { - observer : observer, - symm_key : symm_key, - symm_nonce : symm_nonce, - ipc_stream : ipc_stream, + observer: observer, + symm_key: symm_key, + symm_nonce: symm_nonce, + ipc_stream: ipc_stream, parser_parameters: parameter_packet, }; @@ -81,56 +91,74 @@ impl SecureCommunication { Ok(parser_response) => { if let Some(response_json_str) = parser_response { match self.get_encrypted_normal_response(&cipher_text, response_json_str) { - Ok(response_cipher) => eval_send_one!(self.ipc_stream.write(response_cipher), &self.observer), - Err(err) => debug!("{:?} - Failed to construct a normal response for peer.", err), - } + Ok(response_cipher) => { + eval_send_one!(self.ipc_stream.write(response_cipher), + &self.observer) + } + Err(err) => { + debug!("{:?} - Failed to construct a normal response for peer.", + err) + } + } } else { match self.get_encrypted_error_response(&cipher_text, None) { - Ok(response_cipher) => eval_send_one!(self.ipc_stream.write(response_cipher), &self.observer), - Err(err) => debug!("{:?} - Failed to construct a response error for peer.", err), + Ok(response_cipher) => { + eval_send_one!(self.ipc_stream.write(response_cipher), + &self.observer) + } + Err(err) => { + debug!("{:?} - Failed to construct a response error for peer.", err) + } } } - }, + } Err(err) => { match self.get_encrypted_error_response(&cipher_text, Some(err)) { - Ok(response_cipher) => eval_send_one!(self.ipc_stream.write(response_cipher), &self.observer), - Err(err) => debug!("{:?} - Failed to construct a response error for peer.", err), + Ok(response_cipher) => { + eval_send_one!(self.ipc_stream.write(response_cipher), &self.observer) + } + Err(err) => { + debug!("{:?} - Failed to construct a response error for peer.", err) + } } - }, + } } } } - fn on_receive_payload(&self, cipher_text: &[u8]) -> ::launcher::parser::ResponseType { - let plain_text = try!(::sodiumoxide::crypto::secretbox::open(&cipher_text, &self.symm_nonce, &self.symm_key) - .map_err(|()| ::errors::LauncherError::SymmetricDecipherFailure)); + fn on_receive_payload(&self, cipher_text: &[u8]) -> parser::ResponseType { + let plain_text = try!(secretbox::open(&cipher_text, &self.symm_nonce, &self.symm_key) + .map_err(|()| LauncherError::SymmetricDecipherFailure)); let json_str = try!(parse_result!(String::from_utf8(plain_text), "Invalid UTF-8")); - let json_request = try!(::rustc_serialize::json::Json::from_str(&json_str)); + let json_request = try!(json::Json::from_str(&json_str)); - ::launcher::parser::begin_parse(self.parser_parameters.clone(), &mut ::rustc_serialize::json::Decoder::new(json_request)) + parser::begin_parse(self.parser_parameters.clone(), + &mut json::Decoder::new(json_request)) } fn get_encrypted_normal_response(&self, orig_payload: &[u8], - data : String) -> Result, ::errors::LauncherError> { + data: String) + -> Result, LauncherError> { let normal_response = LauncherNormalResponse { - id : SecureCommunication::get_response_id(orig_payload), + id: SecureCommunication::get_response_id(orig_payload), // TODO(Spandan) // This is inefficient - encoding into a json_str and then again decoding that into a // JSON. Instead get directly into a JSON in ::launcher::parser::ResponseType - data: unwrap_result!(::rustc_serialize::json::Json::from_str(&data[..])), + data: unwrap_result!(json::Json::from_str(&data[..])), }; - let json_str = try!(::rustc_serialize::json::encode(&normal_response)); + let json_str = try!(json::encode(&normal_response)); - let cipher_text = ::sodiumoxide::crypto::secretbox::seal(&json_str.into_bytes(), &self.symm_nonce, &self.symm_key); + let cipher_text = secretbox::seal(&json_str.into_bytes(), &self.symm_nonce, &self.symm_key); Ok(cipher_text) } fn get_encrypted_error_response(&self, orig_payload: &[u8], - error : Option<::errors::LauncherError>) -> Result, ::errors::LauncherError> { + error: Option) + -> Result, LauncherError> { let response_id = SecureCommunication::get_response_id(orig_payload); let (debug_description, error_code) = if let Some(err) = error { @@ -140,18 +168,18 @@ impl SecureCommunication { }; let error_detail = ErrorDetail { - code : error_code as i64, + code: error_code as i64, description: debug_description, }; let error_response = LauncherErrorResponse { - id : response_id, + id: response_id, error: error_detail, }; - let json_str = try!(::rustc_serialize::json::encode(&error_response)); + let json_str = try!(json::encode(&error_response)); - let cipher_text = ::sodiumoxide::crypto::secretbox::seal(&json_str.into_bytes(), &self.symm_nonce, &self.symm_key); + let cipher_text = secretbox::seal(&json_str.into_bytes(), &self.symm_nonce, &self.symm_key); Ok(cipher_text) } @@ -166,18 +194,18 @@ impl SecureCommunication { #[derive(RustcEncodable, Debug)] struct LauncherNormalResponse { - id : String, - data: ::rustc_serialize::json::Json, + id: String, + data: json::Json, } #[derive(RustcEncodable, Debug)] struct LauncherErrorResponse { - id : String, + id: String, error: ErrorDetail, } #[derive(RustcEncodable, Debug)] struct ErrorDetail { - code : i64, + code: i64, description: String, } diff --git a/src/launcher/ipc_server/ipc_session/stream.rs b/src/launcher/ipc_server/ipc_session/stream.rs index 98d9eeb2..2ebb3a4c 100644 --- a/src/launcher/ipc_server/ipc_session/stream.rs +++ b/src/launcher/ipc_server/ipc_session/stream.rs @@ -15,20 +15,27 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::net::TcpStream; +use std::sync::mpsc; + +use bufstream::BufStream; + use maidsafe_utilities::thread::RaiiThreadJoiner; +use errors::LauncherError; const STREAM_WRITER_THREAD_NAME: &'static str = "IpcStreamWriterThread"; pub struct IpcStream { - _raii_joiner : RaiiThreadJoiner, - write_sender : ::std::sync::mpsc::Sender, - reader_stream: ::bufstream::BufStream<::std::net::TcpStream>, + _raii_joiner: RaiiThreadJoiner, + write_sender: mpsc::Sender, + reader_stream: BufStream<::std::net::TcpStream>, } impl IpcStream { - pub fn new(stream: ::std::net::TcpStream) -> Result { - let cloned_stream = try!(stream.try_clone().map_err(|e| ::errors::LauncherError::IpcStreamCloneError(e))); - let (tx, rx) = ::std::sync::mpsc::channel(); + pub fn new(stream: TcpStream) -> Result { + let cloned_stream = try!(stream.try_clone() + .map_err(|e| LauncherError::IpcStreamCloneError(e))); + let (tx, rx) = mpsc::channel(); let joiner = thread!(STREAM_WRITER_THREAD_NAME, move || { IpcStream::handle_write(rx, cloned_stream); @@ -36,9 +43,9 @@ impl IpcStream { }); Ok(IpcStream { - _raii_joiner : RaiiThreadJoiner::new(joiner), - write_sender : tx, - reader_stream: ::bufstream::BufStream::new(stream), + _raii_joiner: RaiiThreadJoiner::new(joiner), + write_sender: tx, + reader_stream: BufStream::new(stream), }) } @@ -54,42 +61,46 @@ impl IpcStream { // Initialising it is an utter waste of cycles and will slow down networking without any // benefits if data exchanged are of considerable magnitude and frequency. #[allow(unsafe_code)] - pub fn read_payload(&mut self) -> Result, ::errors::LauncherError> { + pub fn read_payload(&mut self) -> Result, LauncherError> { use byteorder::ReadBytesExt; let mut size_buffer = [0; 8]; try!(self.fill_buffer(&mut size_buffer[..])); - let size = try!(::std::io::Cursor::new(&size_buffer[..]).read_u64::<::byteorder::LittleEndian>() - .map_err(|err| { - debug!("{:?}", err); - ::errors::LauncherError::FailedReadingStreamPayloadSize - })); + let size = try!(::std::io::Cursor::new(&size_buffer[..]) + .read_u64::<::byteorder::LittleEndian>() + .map_err(|err| { + debug!("{:?}", err); + LauncherError::FailedReadingStreamPayloadSize + })); if size > ::config::MAX_ALLOWED_READ_PAYLOAD_SIZE_BYTES { - return Err(::errors::LauncherError::ReadPayloadSizeProhibitive) + return Err(LauncherError::ReadPayloadSizeProhibitive); } let mut payload = Vec::with_capacity(size as usize); - unsafe { payload.set_len(size as usize); } + unsafe { + payload.set_len(size as usize); + } try!(self.fill_buffer(&mut payload)); Ok(payload) } - pub fn write(&mut self, payload: Vec) -> Result<(), ::errors::LauncherError> { - Ok(try!(self.write_sender.send(WriterEvent::WritePayload(payload)) - .map_err(|err| { - debug!("Error {:?} sending event {:?}", err, err.0); - ::errors::LauncherError::IpcSessionTerminated(None) - }))) + pub fn write(&mut self, payload: Vec) -> Result<(), LauncherError> { + Ok(try!(self.write_sender + .send(WriterEvent::WritePayload(payload)) + .map_err(|err| { + debug!("Error {:?} sending event {:?}", err, err.0); + LauncherError::IpcSessionTerminated(None) + }))) } // This will exit on any error condition the stream writer encounters. The stream reads can // continue. The next write event will however immediately notify the caller about the // writer channel being hung-up so that IPC Session can be terminated gracefully. - fn handle_write(rx: ::std::sync::mpsc::Receiver, mut stream: ::std::net::TcpStream) { + fn handle_write(rx: mpsc::Receiver, mut stream: TcpStream) { use std::io::Write; use byteorder::WriteBytesExt; @@ -98,35 +109,36 @@ impl IpcStream { WriterEvent::WritePayload(payload) => { let size = payload.len() as u64; let mut little_endian_size_bytes = Vec::with_capacity(8); - eval_break!(little_endian_size_bytes.write_u64::<::byteorder::LittleEndian>(size) - .map_err(|err| { - debug!("{:?}", err); - ::errors::LauncherError::FailedWritingStreamPayloadSize - })); + eval_break!( + little_endian_size_bytes.write_u64::<::byteorder::LittleEndian>(size) + .map_err(|err| { + debug!("{:?}", err); + LauncherError::FailedWritingStreamPayloadSize + })); eval_break!(stream.write_all(&little_endian_size_bytes)); eval_break!(stream.write_all(&payload)); - }, + } WriterEvent::Terminate => break, } } } - fn fill_buffer(&mut self, mut buffer_view: &mut [u8]) -> Result<(), ::errors::LauncherError> { - use ::std::io::Read; + fn fill_buffer(&mut self, mut buffer_view: &mut [u8]) -> Result<(), LauncherError> { + use std::io::Read; while buffer_view.len() != 0 { match self.reader_stream.read(&mut buffer_view) { Ok(rxd_bytes) => { if rxd_bytes == 0 { - return Err(::errors::LauncherError::IpcSessionTerminated(None)) + return Err(LauncherError::IpcSessionTerminated(None)); } let temp_buffer_view = buffer_view; buffer_view = &mut temp_buffer_view[rxd_bytes..]; - }, + } Err(ref err) if err.kind() == ::std::io::ErrorKind::Interrupted => (), - Err(err) => return Err(::errors::LauncherError::IpcSessionTerminated(Some(err))) + Err(err) => return Err(LauncherError::IpcSessionTerminated(Some(err))), } } diff --git a/src/launcher/ipc_server/misc.rs b/src/launcher/ipc_server/misc.rs index fab3ca6b..8807aa54 100644 --- a/src/launcher/ipc_server/misc.rs +++ b/src/launcher/ipc_server/misc.rs @@ -17,21 +17,18 @@ use xor_name::XorName; use maidsafe_utilities::thread::RaiiThreadJoiner; +use launcher::ipc_server::ipc_session::{events, EventSenderToSession}; +use safe_nfs::metadata::directory_key::DirectoryKey; pub struct SessionInfo { pub _raii_joiner: RaiiThreadJoiner, - pub event_sender: ::launcher - ::ipc_server - ::ipc_session::EventSenderToSession<::launcher::ipc_server::ipc_session - ::events::ExternalEvent>, + pub event_sender: EventSenderToSession, } impl SessionInfo { - pub fn new(raii_joiner : RaiiThreadJoiner, - event_sender: ::launcher::ipc_server - ::ipc_session - ::EventSenderToSession<::launcher::ipc_server::ipc_session - ::events::ExternalEvent>) -> SessionInfo { + pub fn new(raii_joiner: RaiiThreadJoiner, + event_sender: EventSenderToSession) + -> SessionInfo { SessionInfo { _raii_joiner: raii_joiner, event_sender: event_sender, @@ -41,25 +38,26 @@ impl SessionInfo { impl Drop for SessionInfo { fn drop(&mut self) { - if let Err(err) = self.event_sender.send(::launcher::ipc_server::ipc_session::events::ExternalEvent::Terminate) { + if let Err(err) = self.event_sender.send(events::ExternalEvent::Terminate) { debug!("Failed to send terminate event to session {:?}", err); } } } pub struct AppInfo { - pub app_id : XorName, - pub app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, + pub app_id: XorName, + pub app_root_dir_key: DirectoryKey, pub safe_drive_access: bool, } impl AppInfo { - pub fn new(app_id : XorName, - app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, - safe_drive_access: bool) -> AppInfo { + pub fn new(app_id: XorName, + app_root_dir_key: DirectoryKey, + safe_drive_access: bool) + -> AppInfo { AppInfo { - app_id : app_id, - app_root_dir_key : app_root_dir_key, + app_id: app_id, + app_root_dir_key: app_root_dir_key, safe_drive_access: safe_drive_access, } } diff --git a/src/launcher/ipc_server/mod.rs b/src/launcher/ipc_server/mod.rs index cb03c520..6ad572e9 100644 --- a/src/launcher/ipc_server/mod.rs +++ b/src/launcher/ipc_server/mod.rs @@ -15,13 +15,22 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::collections::HashMap; +use std::net::{Ipv4Addr, TcpListener, TcpStream}; +use std::sync::{Arc, atomic, mpsc, Mutex}; + +use errors::LauncherError; +use launcher::ipc_server::ipc_session::events::ExternalEvent; +use observer::{event_data, IpcObserver}; +use safe_core::client::Client; use xor_name::XorName; use maidsafe_utilities::thread::RaiiThreadJoiner; use maidsafe_utilities::event_sender::EventSender; pub mod events; -pub type EventSenderToServer = EventSender; +pub type EventSenderToServer = EventSender; mod misc; mod ipc_session; @@ -32,59 +41,59 @@ const LISTENER_THIRD_OCTATE_START: u8 = 0; const LISTENER_FOURTH_OCTATE_START: u8 = 1; pub struct IpcServer { - client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - temp_id : u32, - _raii_joiner : RaiiThreadJoiner, - session_event_tx : ::std::sync::mpsc::Sender, - session_event_rx : ::std::sync::mpsc::Receiver, - listener_event_rx : ::std::sync::mpsc::Receiver, - external_event_rx : ::std::sync::mpsc::Receiver, - event_catagory_tx : ::std::sync::mpsc::Sender, - listener_endpoint : String, - listener_stop_flag : ::std::sync::Arc<::std::sync::atomic::AtomicBool>, - verified_sessions : ::std::collections::HashMap, - unverified_sessions : ::std::collections::HashMap, - pending_verifications : ::std::collections::HashMap, - verified_session_observers : Vec<::observer::IpcObserver>, - unverified_session_observers : Vec<::observer::IpcObserver>, - pending_verification_observers: Vec<::observer::IpcObserver>, + client: Arc>, + temp_id: u32, + _raii_joiner: RaiiThreadJoiner, + session_event_tx: mpsc::Sender, + session_event_rx: mpsc::Receiver, + listener_event_rx: mpsc::Receiver, + external_event_rx: mpsc::Receiver, + event_catagory_tx: mpsc::Sender, + listener_endpoint: String, + listener_stop_flag: Arc, + verified_sessions: HashMap, + unverified_sessions: HashMap, + pending_verifications: HashMap, + verified_session_observers: Vec, + unverified_session_observers: Vec, + pending_verification_observers: Vec, } impl IpcServer { - pub fn new(client: ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>) -> Result<(RaiiThreadJoiner, - EventSenderToServer), - ::errors::LauncherError> { - let (session_event_tx, session_event_rx) = ::std::sync::mpsc::channel(); - let (listener_event_tx, listener_event_rx) = ::std::sync::mpsc::channel(); - let (external_event_tx, external_event_rx) = ::std::sync::mpsc::channel(); - let (event_catagory_tx, event_catagory_rx) = ::std::sync::mpsc::channel(); - - let stop_flag = ::std::sync::Arc::new(::std::sync::atomic::AtomicBool::new(false)); - let listener_event_sender = EventSenderToServer:: - ::new(listener_event_tx, - events::IpcServerEventCategory::IpcListenerEvent, - event_catagory_tx.clone()); - - let (joiner, endpoint) = try!(IpcServer::spawn_acceptor(listener_event_sender, stop_flag.clone())); + pub fn new + (client: Arc>) + -> Result<(RaiiThreadJoiner, EventSenderToServer), LauncherError> { + let (session_event_tx, session_event_rx) = mpsc::channel(); + let (listener_event_tx, listener_event_rx) = mpsc::channel(); + let (external_event_tx, external_event_rx) = mpsc::channel(); + let (event_catagory_tx, event_catagory_rx) = mpsc::channel(); + + let stop_flag = Arc::new(atomic::AtomicBool::new(false)); + let listener_event_sender = + EventSenderToServer::::new(listener_event_tx, + events::IpcServerEventCategory::IpcListenerEvent, event_catagory_tx.clone()); + + let (joiner, endpoint) = try!(IpcServer::spawn_acceptor(listener_event_sender, + stop_flag.clone())); let cloned_event_catagory_tx = event_catagory_tx.clone(); let ipc_server_joiner = thread!(IPC_SERVER_THREAD_NAME, move || { let mut ipc_server = IpcServer { - client : client, - temp_id : 0, - _raii_joiner : joiner, - session_event_tx : session_event_tx, - session_event_rx : session_event_rx, - listener_event_rx : listener_event_rx, - external_event_rx : external_event_rx, - event_catagory_tx : cloned_event_catagory_tx, - listener_endpoint : endpoint, - listener_stop_flag : stop_flag, - verified_sessions : ::std::collections::HashMap::new(), - unverified_sessions : ::std::collections::HashMap::new(), - pending_verifications : ::std::collections::HashMap::new(), - verified_session_observers : Vec::with_capacity(2), - unverified_session_observers : Vec::with_capacity(2), + client: client, + temp_id: 0, + _raii_joiner: joiner, + session_event_tx: session_event_tx, + session_event_rx: session_event_rx, + listener_event_rx: listener_event_rx, + external_event_rx: external_event_rx, + event_catagory_tx: cloned_event_catagory_tx, + listener_endpoint: endpoint, + listener_stop_flag: stop_flag, + verified_sessions: HashMap::new(), + unverified_sessions: HashMap::new(), + pending_verifications: HashMap::new(), + verified_session_observers: Vec::with_capacity(2), + unverified_session_observers: Vec::with_capacity(2), pending_verification_observers: Vec::with_capacity(2), }; @@ -93,162 +102,194 @@ impl IpcServer { debug!("Exiting Thread {:?}", IPC_SERVER_THREAD_NAME); }); - let external_event_sender = EventSenderToServer:: - ::new(external_event_tx, - events::IpcServerEventCategory::ExternalEvent, - event_catagory_tx); + let external_event_sender = + EventSenderToServer::::new(external_event_tx, + events::IpcServerEventCategory::ExternalEvent, event_catagory_tx); - Ok((RaiiThreadJoiner::new(ipc_server_joiner), external_event_sender)) + Ok((RaiiThreadJoiner::new(ipc_server_joiner), + external_event_sender)) } - fn run(&mut self, event_catagory_rx: ::std::sync::mpsc::Receiver) { + fn run(&mut self, event_catagory_rx: mpsc::Receiver) { for event_category in event_catagory_rx.iter() { match event_category { events::IpcServerEventCategory::IpcListenerEvent => { if let Ok(listner_event) = self.listener_event_rx.try_recv() { match listner_event { - events::IpcListenerEvent::IpcListenerAborted(error) => self.on_ipc_listener_aborted(error), - events::IpcListenerEvent::SpawnIpcSession(tcp_stream) => self.on_spawn_ipc_session(tcp_stream), + events::IpcListenerEvent::IpcListenerAborted(error) => { + self.on_ipc_listener_aborted(error) + } + events::IpcListenerEvent::SpawnIpcSession(tcp_stream) => { + self.on_spawn_ipc_session(tcp_stream) + } } } - }, + } events::IpcServerEventCategory::IpcSessionEvent => { if let Ok(session_event) = self.session_event_rx.try_recv() { match session_event { - events::IpcSessionEvent::VerifySession(detail) => self.on_verify_session(detail), - events::IpcSessionEvent::IpcSessionTerminated(detail) => self.on_ipc_session_terminated(detail), + events::IpcSessionEvent::VerifySession(detail) => { + self.on_verify_session(detail) + } + events::IpcSessionEvent::IpcSessionTerminated(detail) => { + self.on_ipc_session_terminated(detail) + } } } - }, + } events::IpcServerEventCategory::ExternalEvent => { if let Ok(external_event) = self.external_event_rx.try_recv() { match external_event { - events::ExternalEvent::EndSession(app_id) => self.on_end_session(app_id), - events::ExternalEvent::GetListenerEndpoint(sender) => self.on_get_listener_endpoint(sender), - events::ExternalEvent::AppActivated(activation_detail) => self.on_app_activated(activation_detail), - events::ExternalEvent::ChangeSafeDriveAccess(app_id, is_allowed) => self.on_change_safe_drive_access(app_id, is_allowed), - events::ExternalEvent::RegisterVerifiedSessionObserver(obs) => self.on_register_verified_session_observer(obs), - events::ExternalEvent::RegisterUnverifiedSessionObserver(obs) => self.on_register_unverified_session_observer(obs), - events::ExternalEvent::RegisterPendingVerificationObserver(obs) => self.on_register_pending_verification_observer(obs), + events::ExternalEvent::EndSession(app_id) => { + self.on_end_session(app_id) + } + events::ExternalEvent::GetListenerEndpoint(sender) => { + self.on_get_listener_endpoint(sender) + } + events::ExternalEvent::AppActivated(activation_detail) => { + self.on_app_activated(activation_detail) + } + events::ExternalEvent::ChangeSafeDriveAccess(app_id, is_allowed) => { + self.on_change_safe_drive_access(app_id, is_allowed) + } + events::ExternalEvent::RegisterVerifiedSessionObserver(obs) => { + self.on_register_verified_session_observer(obs) + } + events::ExternalEvent::RegisterUnverifiedSessionObserver(obs) => { + self.on_register_unverified_session_observer(obs) + } + events::ExternalEvent::RegisterPendingVerificationObserver(obs) => { + self.on_register_pending_verification_observer(obs) + } events::ExternalEvent::Terminate => break, } } - }, + } } } } - fn on_spawn_ipc_session(&mut self, stream: ::std::net::TcpStream) { + fn on_spawn_ipc_session(&mut self, stream: TcpStream) { let event_sender = EventSenderToServer:: ::new(self.session_event_tx.clone(), events::IpcServerEventCategory::IpcSessionEvent, self.event_catagory_tx.clone()); - match ipc_session::IpcSession::new(event_sender, - self.temp_id, - stream) { + match ipc_session::IpcSession::new(event_sender, self.temp_id, stream) { Ok((raii_joiner, event_sender)) => { - if let Some(_) = self.unverified_sessions.insert(self.temp_id, - misc::SessionInfo::new(raii_joiner, - event_sender)) { - debug!("Unverified session existed even after all temporary ids are exhausted. Terminating that session ..."); + if let Some(_) = self.unverified_sessions + .insert(self.temp_id, + misc::SessionInfo::new(raii_joiner, event_sender)) { + debug!("Unverified session existed even after all temporary ids are \ + exhausted. Terminating that session ..."); } else { - let data = ::observer::event_data::UnverifiedSession { - id : self.temp_id, - action: ::observer::event_data::Action::Added, + let data = event_data::UnverifiedSession { + id: self.temp_id, + action: event_data::Action::Added, }; group_send!(data, &mut self.unverified_session_observers); } - }, + } Err(err) => debug!("IPC Session spawning failed for peer {:?}", err), } self.temp_id = self.temp_id.wrapping_add(1); } #[allow(unused)] - fn on_ipc_listener_aborted(&self, error: Box<::errors::LauncherError>) { + fn on_ipc_listener_aborted(&self, error: Box) { let error = *error; } fn on_verify_session(&mut self, detail: Box<(u32, String)>) { let (temp_id, nonce) = *detail; - match (self.unverified_sessions.remove(&temp_id), self.pending_verifications.remove(&nonce)) { + match (self.unverified_sessions.remove(&temp_id), + self.pending_verifications.remove(&nonce)) { (Some(session_info), Some(app_info)) => { let app_detail = ipc_session::events::event_data::AppDetail { - client : self.client.clone(), - app_id : app_info.app_id.clone(), - app_root_dir_key : app_info.app_root_dir_key, + client: self.client.clone(), + app_id: app_info.app_id.clone(), + app_root_dir_key: app_info.app_root_dir_key, safe_drive_access: app_info.safe_drive_access, }; if send_one!(app_detail, &session_info.event_sender).is_err() { - debug!("Unable to communicate with the session via channel. Session will be terminated."); - } else if let Some(_) = self.verified_sessions.insert(app_info.app_id.clone(), session_info) { - debug!("Detected an attempt by an app to connect twice. Previous instance will be terminated."); + debug!("Unable to communicate with the session via channel. Session will be \ + terminated."); + } else if let Some(_) = self.verified_sessions + .insert(app_info.app_id.clone(), session_info) { + debug!("Detected an attempt by an app to connect twice. Previous instance \ + will be terminated."); } else { - let data = ::observer::event_data::VerifiedSession { - id : app_info.app_id, - action: ::observer::event_data::Action::Added, + let data = event_data::VerifiedSession { + id: app_info.app_id, + action: event_data::Action::Added, }; group_send!(data, &mut self.verified_session_observers); } - }, - _ => debug!("Temp Id {:?} and/or Nonce {:?} invalid. Possible security breach - situation salvaged.", - temp_id, nonce), + } + _ => { + debug!("Temp Id {:?} and/or Nonce {:?} invalid. Possible security breach - \ + situation salvaged.", + temp_id, + nonce) + } } - let data = ::observer::event_data::UnverifiedSession { - id : temp_id, - action: ::observer::event_data::Action::Removed(None), + let data = event_data::UnverifiedSession { + id: temp_id, + action: event_data::Action::Removed(None), }; group_send!(data, &mut self.unverified_session_observers); - let data = ::observer::event_data::PendingVerification { - nonce : nonce, - action: ::observer::event_data::Action::Removed(None), + let data = event_data::PendingVerification { + nonce: nonce, + action: event_data::Action::Removed(None), }; group_send!(data, &mut self.pending_verification_observers); } - fn on_ipc_session_terminated(&mut self, detail: Box) { + fn on_ipc_session_terminated(&mut self, + detail: Box) { let detail = *detail; match detail.id { events::event_data::SessionId::AppId(app_id) => { let _ = self.verified_sessions.remove(&*app_id); - let data = ::observer::event_data::VerifiedSession { - id : *app_id, - action: ::observer::event_data::Action::Removed(Some(detail.reason)), + let data = event_data::VerifiedSession { + id: *app_id, + action: event_data::Action::Removed(Some(detail.reason)), }; group_send!(data, &mut self.verified_session_observers); - }, + } events::event_data::SessionId::TempId(temp_id) => { let _ = self.unverified_sessions.remove(&temp_id); - let data = ::observer::event_data::UnverifiedSession { - id : temp_id, - action: ::observer::event_data::Action::Removed(Some(detail.reason)), + let data = event_data::UnverifiedSession { + id: temp_id, + action: event_data::Action::Removed(Some(detail.reason)), }; group_send!(data, &mut self.unverified_session_observers); - }, + } }; } fn on_app_activated(&mut self, activation_detail: Box) { let detail = *activation_detail; - if let Some(_) = self.pending_verifications.insert(detail.nonce.clone(), - misc::AppInfo::new(detail.app_id, - detail.app_root_dir_key, - detail.safe_drive_access)) { + if let Some(_) = self.pending_verifications + .insert(detail.nonce.clone(), + misc::AppInfo::new(detail.app_id, + detail.app_root_dir_key, + detail.safe_drive_access)) { // TODO(Spandan) handle this security hole. - error!("Same nonce was already given to an app pending verification. This is a security hole not fixed in this iteration."); + error!("Same nonce was already given to an app pending verification. This is a \ + security hole not fixed in this iteration."); error!("Issues like mixed-up safe drive access could arise."); error!("Dropping the previous app information and re-assigning nonce to a new app"); } else { - let data = ::observer::event_data::PendingVerification { - nonce : detail.nonce, - action: ::observer::event_data::Action::Added, + let data = event_data::PendingVerification { + nonce: detail.nonce, + action: event_data::Action::Added, }; group_send!(data, &mut self.pending_verification_observers); } @@ -258,11 +299,9 @@ impl IpcServer { let mut send_failed = false; if let Some(session_info) = self.verified_sessions.get_mut(&app_id) { - send_failed = session_info.event_sender.send(::launcher - ::ipc_server - ::ipc_session - ::events - ::ExternalEvent::ChangeSafeDriveAccess(is_allowed)).is_err(); + send_failed = session_info.event_sender + .send(ExternalEvent::ChangeSafeDriveAccess(is_allowed)) + .is_err(); } else { for (_, app_info) in self.pending_verifications.iter_mut() { if app_info.app_id == app_id { @@ -275,9 +314,10 @@ impl IpcServer { if send_failed { let _ = self.verified_sessions.remove(&app_id); - let data = ::observer::event_data::VerifiedSession { - id : app_id, - action: ::observer::event_data::Action::Removed(Some(::errors::LauncherError::ReceiverChannelDisconnected)), + let data = event_data::VerifiedSession { + id: app_id, + action: + event_data::Action::Removed(Some(LauncherError::ReceiverChannelDisconnected)), }; group_send!(data, &mut self.verified_session_observers); } @@ -289,15 +329,15 @@ impl IpcServer { } } - fn on_register_verified_session_observer(&mut self, observer: ::observer::IpcObserver) { + fn on_register_verified_session_observer(&mut self, observer: IpcObserver) { self.verified_session_observers.push(observer); } - fn on_register_unverified_session_observer(&mut self, observer: ::observer::IpcObserver) { + fn on_register_unverified_session_observer(&mut self, observer: IpcObserver) { self.unverified_session_observers.push(observer); } - fn on_register_pending_verification_observer(&mut self, observer: ::observer::IpcObserver) { + fn on_register_pending_verification_observer(&mut self, observer: IpcObserver) { self.pending_verification_observers.push(observer); } @@ -312,38 +352,42 @@ impl IpcServer { } if let Some(launcher_nonce) = found { - let _ = unwrap_option!(self.pending_verifications.remove(&launcher_nonce), "Logic Error - Report a bug."); + let _ = unwrap_option!(self.pending_verifications.remove(&launcher_nonce), + "Logic Error - Report a bug."); } else { - debug!("IPC Server has no knowledge of the given App-Id {:?} for removal", app_id); + debug!("IPC Server has no knowledge of the given App-Id {:?} for removal", + app_id); } } } fn spawn_acceptor(event_sender: EventSenderToServer, - stop_flag : ::std::sync::Arc<::std::sync::atomic::AtomicBool>) -> Result<(RaiiThreadJoiner, - String), - ::errors::LauncherError> { + stop_flag: Arc) + -> Result<(RaiiThreadJoiner, String), LauncherError> { let mut third_octate = LISTENER_THIRD_OCTATE_START; let mut fourth_octate = LISTENER_FOURTH_OCTATE_START; let ipc_listener; loop { - let local_ip = ::std::net::Ipv4Addr::new(127, 0, third_octate, fourth_octate); + let local_ip = Ipv4Addr::new(127, 0, third_octate, fourth_octate); let local_endpoint = (local_ip, 0); - match ::std::net::TcpListener::bind(local_endpoint) { + match TcpListener::bind(local_endpoint) { Ok(listener) => { ipc_listener = listener; break; - }, + } Err(err) => { - debug!("Failed binding IPC Server on 127.0.{}.{} with error {:?}. Trying net IP...", - third_octate, fourth_octate, err); + debug!("Failed binding IPC Server on 127.0.{}.{} with error {:?}. Trying net \ + IP...", + third_octate, + fourth_octate, + err); if fourth_octate == 255 { if third_octate == 255 { - return Err(::errors::LauncherError::IpcListenerCouldNotBeBound) + return Err(LauncherError::IpcListenerCouldNotBeBound); } else { third_octate += 1; fourth_octate = LISTENER_FOURTH_OCTATE_START; @@ -351,16 +395,14 @@ impl IpcServer { } else { fourth_octate += 1; } - }, + } } } let local_endpoint = format!("{}", unwrap_result!(ipc_listener.local_addr())); let joiner = thread!(IPC_LISTENER_THREAD_NAME, move || { - IpcServer::handle_accept(ipc_listener, - event_sender, - stop_flag); + IpcServer::handle_accept(ipc_listener, event_sender, stop_flag); debug!("Exiting Thread {:?}", IPC_LISTENER_THREAD_NAME); }); @@ -368,25 +410,28 @@ impl IpcServer { Ok((RaiiThreadJoiner::new(joiner), local_endpoint)) } - fn handle_accept(ipc_listener: ::std::net::TcpListener, + fn handle_accept(ipc_listener: TcpListener, event_sender: EventSenderToServer, - stop_flag : ::std::sync::Arc<::std::sync::atomic::AtomicBool>) { - loop { - match ipc_listener.accept().map_err(|e| ::errors::LauncherError::IpcListenerAborted(e)) { + stop_flag: Arc) { + loop { + match ipc_listener.accept() + .map_err(|e| LauncherError::IpcListenerAborted(e)) { Ok((stream, _)) => { - if stop_flag.load(::std::sync::atomic::Ordering::SeqCst) { + if stop_flag.load(atomic::Ordering::SeqCst) { break; } else { - if let Err(_) = event_sender.send(events::IpcListenerEvent::SpawnIpcSession(stream)) { + if let Err(_) = event_sender.send( + events::IpcListenerEvent::SpawnIpcSession(stream)) { break; } } - }, + } Err(accept_error) => { debug!("IPC Listener aborted !!"); - let _ = event_sender.send(events::IpcListenerEvent::IpcListenerAborted(Box::new(accept_error))); + let _ = event_sender.send( + events::IpcListenerEvent::IpcListenerAborted(Box::new(accept_error))); break; - }, + } } } } @@ -394,8 +439,8 @@ impl IpcServer { impl Drop for IpcServer { fn drop(&mut self) { - self.listener_stop_flag.store(true, ::std::sync::atomic::Ordering::SeqCst); - if let Ok(stream) = ::std::net::TcpStream::connect(&self.listener_endpoint[..]) { + self.listener_stop_flag.store(true, atomic::Ordering::SeqCst); + if let Ok(stream) = TcpStream::connect(&self.listener_endpoint[..]) { if let Err(err) = stream.shutdown(::std::net::Shutdown::Both) { debug!("Error shutting down terminator stream: {:?}", err); } @@ -407,31 +452,35 @@ impl Drop for IpcServer { mod test { use super::*; use std::io::Read; - use std::sync::{Arc, Mutex}; + use std::net::TcpStream; + use std::time::Duration; + use std::sync::{Arc, mpsc, Mutex}; use maidsafe_utilities::thread::RaiiThreadJoiner; + use safe_core::utility::test_utils; + use launcher::ipc_server::events::ExternalEvent; #[test] fn spawn_and_shut_ipc_server() { - let client = Arc::new(Mutex::new(unwrap_result!(::safe_core::utility::test_utils::get_client()))); + let client = Arc::new(Mutex::new(unwrap_result!(test_utils::get_client()))); let (_raii_joiner_0, event_sender) = unwrap_result!(IpcServer::new(client)); - let (tx, rx) = ::std::sync::mpsc::channel(); - unwrap_result!(event_sender.send(::launcher::ipc_server::events::ExternalEvent::GetListenerEndpoint(tx))); + let (tx, rx) = mpsc::channel(); + unwrap_result!(event_sender.send(ExternalEvent::GetListenerEndpoint(tx))); let listener_ep = unwrap_result!(rx.recv()); - let mut stream = unwrap_result!(::std::net::TcpStream::connect(&listener_ep[..])); + let mut stream = unwrap_result!(TcpStream::connect(&listener_ep[..])); let _raii_joiner_1 = RaiiThreadJoiner::new(thread!("ReaderThread", move || { let mut buffer = [0; 5]; assert_eq!(unwrap_result!(stream.read(&mut buffer)), 0); })); - let duration = ::std::time::Duration::from_millis(3000); + let duration = Duration::from_millis(3000); ::std::thread::sleep(duration); // Terminate to exit this test - otherwise the raii_joiners will hang this test - this is // by design. So there is no way out but graceful termination which is what this entire // design strives for. - unwrap_result!(event_sender.send(::launcher::ipc_server::events::ExternalEvent::Terminate)); + unwrap_result!(event_sender.send(ExternalEvent::Terminate)); } } diff --git a/src/launcher/mod.rs b/src/launcher/mod.rs index 56001655..ab801501 100644 --- a/src/launcher/mod.rs +++ b/src/launcher/mod.rs @@ -15,6 +15,8 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::sync::{Arc, mpsc}; + /// Events that can be communicated to the IPC-handling module. pub use self::ipc_server::events::ExternalEvent as IpcExternalEvent; /// Events that can be communicated to the app-handling module. @@ -22,6 +24,13 @@ pub use self::app_handler::events::{AppHandlerEvent, event_data as app_handler_e use maidsafe_utilities::thread::RaiiThreadJoiner; +use safe_core::client::Client; +use safe_nfs::{UNVERSIONED_DIRECTORY_LISTING_TAG, AccessLevel}; +use safe_nfs::helper::{file_helper, directory_helper}; + +use config::{LAUNCHER_GLOBAL_DIRECTORY_NAME, LAUNCHER_GLOBAL_CONFIG_FILE_NAME, SAFE_DRIVE_DIR_NAME}; +use errors::LauncherError; + mod parser; mod ipc_server; mod app_handler; @@ -35,51 +44,53 @@ mod app_handler; /// event senders, clone it and distribute it to other threads. These event senders will help /// communicate with the core library in a completely asynchronous and thread safe manner. pub struct Launcher { - _raii_joiners : Vec, - ipc_event_sender : ipc_server::EventSenderToServer, - app_handler_event_sender: ::std::sync::mpsc::Sender, + _raii_joiners: Vec, + ipc_event_sender: ipc_server::EventSenderToServer, + app_handler_event_sender: mpsc::Sender, } impl Launcher { /// Creates a new self-managed Launcher instance, which is a packet that will intilise and /// store the library state. Dropping this packet would be enough to gracefully exit the /// library by initiaing a domino effect via RAII. - pub fn new(client: ::safe_core::client::Client) -> Result { - let client = ::std::sync::Arc::new(::std::sync::Mutex::new(client)); + pub fn new(client: Client) -> Result { + let client = Arc::new(::std::sync::Mutex::new(client)); - let directory_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(client.clone()); + let directory_helper = directory_helper::DirectoryHelper::new(client.clone()); - let launcher_config_dir_name = ::config::LAUNCHER_GLOBAL_DIRECTORY_NAME.to_string(); - let launcher_config_dir = try!(directory_helper.get_configuration_directory_listing(launcher_config_dir_name)); + let launcher_config_dir_name = LAUNCHER_GLOBAL_DIRECTORY_NAME.to_string(); + let launcher_config_dir = + try!(directory_helper.get_configuration_directory_listing(launcher_config_dir_name)); if launcher_config_dir.get_files() .iter() - .find(|file| file.get_name() == ::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME) + .find(|file| file.get_name() == LAUNCHER_GLOBAL_CONFIG_FILE_NAME) .is_none() { - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(client.clone()); - let writer = try!(file_helper.create(::config::LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string(), + let file_helper = file_helper::FileHelper::new(client.clone()); + let writer = try!(file_helper.create(LAUNCHER_GLOBAL_CONFIG_FILE_NAME.to_string(), Vec::new(), launcher_config_dir)); let _ = try!(writer.close()); } let mut user_root_directory = try!(directory_helper.get_user_root_directory_listing()); - let safe_drive_dir_name = ::config::SAFE_DRIVE_DIR_NAME.to_string(); + let safe_drive_dir_name = SAFE_DRIVE_DIR_NAME.to_string(); if user_root_directory.find_sub_directory(&safe_drive_dir_name).is_none() { - let _ = try!(directory_helper.create(safe_drive_dir_name, - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, + let _ = try!(directory_helper.create(safe_drive_dir_name, + UNVERSIONED_DIRECTORY_LISTING_TAG, Vec::new(), false, - ::safe_nfs::AccessLevel::Private, + AccessLevel::Private, Some(&mut user_root_directory))); } let (ipc_raii_joiner, ipc_event_sender) = try!(ipc_server::IpcServer::new(client.clone())); - let (app_raii_joiner, app_event_sender) = app_handler::AppHandler::new(client, ipc_event_sender.clone()); + let (app_raii_joiner, app_event_sender) = + app_handler::AppHandler::new(client, ipc_event_sender.clone()); Ok(Launcher { - _raii_joiners : vec![app_raii_joiner, ipc_raii_joiner], - ipc_event_sender : ipc_event_sender, + _raii_joiners: vec![app_raii_joiner, ipc_raii_joiner], + ipc_event_sender: ipc_event_sender, app_handler_event_sender: app_event_sender, }) } @@ -91,7 +102,7 @@ impl Launcher { /// Event Sender to communicate with the App Handler, for e.g. to register observers, add an app /// to Laucher, remove or modify an already added app, etc. - pub fn get_app_handler_event_sender(&self) -> &::std::sync::mpsc::Sender { + pub fn get_app_handler_event_sender(&self) -> &mpsc::Sender { &self.app_handler_event_sender } } @@ -99,10 +110,12 @@ impl Launcher { impl Drop for Launcher { fn drop(&mut self) { if let Err(err) = self.ipc_event_sender.send(IpcExternalEvent::Terminate) { - debug!("Error {:?} terminating IPC-Server - Probably already terminated.", err); + debug!("Error {:?} terminating IPC-Server - Probably already terminated.", + err); } if let Err(err) = self.app_handler_event_sender.send(AppHandlerEvent::Terminate) { - debug!("Error {:?} terminating App-Handler - Probably already terminated.", err); + debug!("Error {:?} terminating App-Handler - Probably already terminated.", + err); } } } @@ -110,36 +123,43 @@ impl Drop for Launcher { #[cfg(test)] mod tests { use super::*; + use std::sync::{Arc, Mutex}; + use config::SAFE_DRIVE_DIR_NAME; + use safe_core::utility; + use safe_core::client::Client; + use safe_nfs::helper::directory_helper::DirectoryHelper; #[test] fn initialise_safe_drive_dir() { - let pin = unwrap_result!(::safe_core::utility::generate_random_string(10)); - let keyword = unwrap_result!(::safe_core::utility::generate_random_string(10)); - let password = unwrap_result!(::safe_core::utility::generate_random_string(10)); + let pin = unwrap_result!(utility::generate_random_string(10)); + let keyword = unwrap_result!(utility::generate_random_string(10)); + let password = unwrap_result!(utility::generate_random_string(10)); - let client = unwrap_result!(::safe_core::client::Client::create_account(keyword.clone(), - pin.clone(), - password.clone())); + let client = unwrap_result!(Client::create_account(keyword.clone(), + pin.clone(), + password.clone())); - let safe_drive_directory_name = ::config::SAFE_DRIVE_DIR_NAME.to_string(); - let arc_client = ::std::sync::Arc::new(::std::sync::Mutex::new(client)); - let directory_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(arc_client.clone()); + let safe_drive_directory_name = SAFE_DRIVE_DIR_NAME.to_string(); + let arc_client = Arc::new(Mutex::new(client)); + let directory_helper = DirectoryHelper::new(arc_client.clone()); // client should not have SAFEDrive in user root directory { - let user_root_directory = unwrap_result!(directory_helper.get_user_root_directory_listing()); + let user_root_directory = + unwrap_result!(directory_helper.get_user_root_directory_listing()); assert!(user_root_directory.find_sub_directory(&safe_drive_directory_name).is_none()); } // Create Launcher instance { - let client = unwrap_result!(::safe_core::client::Client::log_in(keyword, pin, password)); + let client = unwrap_result!(Client::log_in(keyword, pin, password)); let _ = Launcher::new(client); } // client should have SAFEDrive in user root directory { - let user_root_directory = unwrap_result!(directory_helper.get_user_root_directory_listing()); + let user_root_directory = + unwrap_result!(directory_helper.get_user_root_directory_listing()); assert!(user_root_directory.find_sub_directory(&safe_drive_directory_name).is_some()); } } diff --git a/src/launcher/parser/dns/add_service_v1_0.rs b/src/launcher/parser/dns/add_service_v1_0.rs index 89461eba..52894006 100644 --- a/src/launcher/parser/dns/add_service_v1_0.rs +++ b/src/launcher/parser/dns/add_service_v1_0.rs @@ -15,23 +15,26 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; use routing::Data; +use safe_dns::dns_operations::DnsOperations; #[derive(RustcDecodable, Debug)] pub struct AddService { - pub long_name : String, - pub service_name : String, - pub is_path_shared : bool, + pub long_name: String, + pub service_name: String, + pub is_path_shared: bool, pub service_home_dir_path: String, } -impl ::launcher::parser::traits::Action for AddService { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for AddService { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } - let tokens = ::launcher::parser::helper::tokenise_path(&self.service_home_dir_path, false); + let tokens = helper::tokenise_path(&self.service_home_dir_path, false); let start_dir_key = if self.is_path_shared { ¶ms.safe_drive_dir_key @@ -39,53 +42,60 @@ impl ::launcher::parser::traits::Action for AddService { ¶ms.app_root_dir_key }; - let dir_to_map = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let dir_to_map = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()).clone(); - let dns_operation = try!(::safe_dns::dns_operations::DnsOperations::new(params.client.clone())); - let struct_data = try!(dns_operation.add_service(&self.long_name, - (self.service_name.clone(), dir_to_map.get_key().clone()), - &signing_key, - None)); - try!(unwrap_result!(params.client.lock()).post(Data::StructuredData(struct_data), None)); - Ok(None) + let signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()) + .clone(); + let dns_operation = try!(DnsOperations::new(params.client.clone())); + let struct_data = try!(dns_operation.add_service(&self.long_name, + (self.service_name.clone(), + dir_to_map.get_key().clone()), + &signing_key, + None)); + try!(unwrap_result!(params.client.lock()).post(Data::StructuredData(struct_data), None)); + Ok(None) } } #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::dns::register_dns_v1_0::RegisterDns; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_core::utility; + use safe_nfs::helper::directory_helper::DirectoryHelper; + use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; const TEST_DIR_NAME: &'static str = "test_dir"; #[test] fn add_dns_service() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, - Vec::new(), - false, - ::safe_nfs::AccessLevel::Public, - Some(&mut app_root_dir))); - let public_name = unwrap_result!(::safe_core::utility::generate_random_string(10)); - let mut register_request = ::launcher::parser::dns::register_dns_v1_0::RegisterDns { - long_name : public_name.clone(), - service_name : "www".to_string(), - is_path_shared : false, + UNVERSIONED_DIRECTORY_LISTING_TAG, + Vec::new(), + false, + AccessLevel::Public, + Some(&mut app_root_dir))); + let public_name = unwrap_result!(utility::generate_random_string(10)); + let mut register_request = RegisterDns { + long_name: public_name.clone(), + service_name: "www".to_string(), + is_path_shared: false, service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), }; assert!(register_request.execute(parameter_packet.clone()).is_ok()); let mut request = AddService { - long_name : public_name, - service_name : "blog".to_string(), - is_path_shared : false, + long_name: public_name, + service_name: "blog".to_string(), + is_path_shared: false, service_home_dir_path: format!("/{}", TEST_DIR_NAME).to_string(), }; diff --git a/src/launcher/parser/dns/mod.rs b/src/launcher/parser/dns/mod.rs index e25f2904..82efe0a2 100644 --- a/src/launcher/parser/dns/mod.rs +++ b/src/launcher/parser/dns/mod.rs @@ -15,40 +15,77 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::fmt; + +use rustc_serialize::Decoder; + +use errors::LauncherError; +use launcher::parser::{ParameterPacket, ResponseType, traits}; + mod add_service_v1_0; mod register_dns_v1_0; -pub fn action_dispatcher(params : ::launcher::parser::ParameterPacket, +pub fn action_dispatcher(params: ParameterPacket, mut remaining_tokens: Vec, - version : f32, - decoder : &mut D) -> ::launcher::parser::ResponseType - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { + version: f32, + decoder: &mut D) + -> ResponseType + where D: Decoder, + D::Error: fmt::Debug +{ if remaining_tokens.len() > 1 { - return Err(::errors::LauncherError::SpecificParseError("Extra unrecognised tokens in endpoint.".to_string())) + return Err(LauncherError::SpecificParseError("Extra unrecognised tokens in endpoint." + .to_string())); } - let action_str = try!(parse_option!(remaining_tokens.pop(), "Invalid endpoint - Action not found.")); + let action_str = try!(parse_option!(remaining_tokens.pop(), + "Invalid endpoint - Action not found.")); let mut action = try!(get_action(&action_str, version, decoder)); action.execute(params) } -fn get_action(action_str: &str, version: f32, decoder: &mut D) -> Result, ::errors::LauncherError> - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { +fn get_action(action_str: &str, + version: f32, + decoder: &mut D) + -> Result, LauncherError> + where D: Decoder, + D::Error: fmt::Debug +{ use rustc_serialize::Decodable; - let version_err = Err(::errors::LauncherError::SpecificParseError(format!("Unsupported version {:?} for this endpoint.", version))); + let version_err = Err(LauncherError::SpecificParseError(format!("Unsupported version {:?} \ + for this endpoint.", + version))); Ok(match action_str { - "register-dns" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| register_dns_v1_0::RegisterDns::decode(d)), ""))), - _ => return version_err, - }, - "add-service" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| add_service_v1_0::AddService::decode(d)), ""))), - _ => return version_err, - }, - _ => return Err(::errors::LauncherError::SpecificParseError(format!("Unsupported action {:?} for this endpoint.", action_str))), + "register-dns" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + register_dns_v1_0::RegisterDns::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "add-service" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + add_service_v1_0::AddService::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + _ => { + return Err(LauncherError::SpecificParseError(format!("Unsupported action {:?} for \ + this endpoint.", + action_str))) + } }) } diff --git a/src/launcher/parser/dns/register_dns_v1_0.rs b/src/launcher/parser/dns/register_dns_v1_0.rs index 76414e73..c5da433e 100644 --- a/src/launcher/parser/dns/register_dns_v1_0.rs +++ b/src/launcher/parser/dns/register_dns_v1_0.rs @@ -15,23 +15,28 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use sodiumoxide::crypto::box_; + use routing::Data; +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_dns::dns_operations::DnsOperations; #[derive(RustcDecodable, Debug)] pub struct RegisterDns { - pub long_name : String, - pub service_name : String, - pub is_path_shared : bool, + pub long_name: String, + pub service_name: String, + pub is_path_shared: bool, pub service_home_dir_path: String, } -impl ::launcher::parser::traits::Action for RegisterDns { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for RegisterDns { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } - let tokens = ::launcher::parser::helper::tokenise_path(&self.service_home_dir_path, false); + let tokens = helper::tokenise_path(&self.service_home_dir_path, false); let start_dir_key = if self.is_path_shared { ¶ms.safe_drive_dir_key @@ -39,15 +44,20 @@ impl ::launcher::parser::traits::Action for RegisterDns { ¶ms.app_root_dir_key }; - let dir_to_map = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let dir_to_map = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let (msg_public_key, msg_secret_key) = ::sodiumoxide::crypto::box_::gen_keypair(); + let (msg_public_key, msg_secret_key) = box_::gen_keypair(); let services = vec![(self.service_name.clone(), (dir_to_map.get_key().clone()))]; - let public_signing_key = try!(unwrap_result!(params.client.lock()).get_public_signing_key()).clone(); - let secret_signing_key = try!(unwrap_result!(params.client.lock()).get_secret_signing_key()).clone(); - let dns_operation = try!(::safe_dns::dns_operations::DnsOperations::new(params.client.clone())); + let public_signing_key = try!(unwrap_result!(params.client.lock()) + .get_public_signing_key()) + .clone(); + let secret_signing_key = try!(unwrap_result!(params.client.lock()) + .get_secret_signing_key()) + .clone(); + let dns_operation = try!(DnsOperations::new(params.client + .clone())); let struct_data = try!(dns_operation.register_dns(self.long_name.clone(), &msg_public_key, &msg_secret_key, @@ -63,27 +73,31 @@ impl ::launcher::parser::traits::Action for RegisterDns { #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_core::utility; + use safe_nfs::helper::directory_helper::DirectoryHelper; + use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; const TEST_DIR_NAME: &'static str = "test_dir"; #[test] fn register_dns() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, - Vec::new(), - false, - ::safe_nfs::AccessLevel::Public, - Some(&mut app_root_dir))); - let public_name = unwrap_result!(::safe_core::utility::generate_random_string(10)); + UNVERSIONED_DIRECTORY_LISTING_TAG, + Vec::new(), + false, + AccessLevel::Public, + Some(&mut app_root_dir))); + let public_name = unwrap_result!(utility::generate_random_string(10)); let mut request = RegisterDns { - long_name : public_name, - service_name : "www".to_string(), - is_path_shared : false, + long_name: public_name, + service_name: "www".to_string(), + is_path_shared: false, service_home_dir_path: "/test_dir2".to_string(), }; assert!(request.execute(parameter_packet.clone()).is_err()); diff --git a/src/launcher/parser/helper.rs b/src/launcher/parser/helper.rs index 54ef6207..7cdd9c0f 100644 --- a/src/launcher/parser/helper.rs +++ b/src/launcher/parser/helper.rs @@ -15,6 +15,14 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use std::sync::{Arc, Mutex}; + +use errors::LauncherError; +use safe_core::client::Client; +use safe_nfs::metadata::directory_key::DirectoryKey; +use safe_nfs::helper::directory_helper::DirectoryHelper; +use safe_nfs::directory_listing::DirectoryListing; + pub fn tokenise_path(path: &str, keep_empty_splits: bool) -> Vec { path.split(|element| element == '/') .filter(|token| keep_empty_splits || token.len() != 0) @@ -22,21 +30,23 @@ pub fn tokenise_path(path: &str, keep_empty_splits: bool) -> Vec { .collect() } -pub fn get_final_subdirectory(client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - tokens : &Vec, - starting_directory: Option<&::safe_nfs::metadata::directory_key::DirectoryKey>) -> Result<::safe_nfs::directory_listing::DirectoryListing, - ::errors::LauncherError> { - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(client); +pub fn get_final_subdirectory(client: Arc>, + tokens: &Vec, + starting_directory: Option<&DirectoryKey>) + -> Result { + let dir_helper = DirectoryHelper::new(client); let mut current_dir_listing = match starting_directory { Some(directory_key) => try!(dir_helper.get(directory_key)), - None => try!(dir_helper.get_user_root_directory_listing()), + None => try!(dir_helper.get_user_root_directory_listing()), }; for it in tokens.iter() { current_dir_listing = { - let current_dir_metadata = try!(current_dir_listing.get_sub_directories().iter().find(|a| *a.get_name() == *it) - .ok_or(::errors::LauncherError::PathNotFound)); + let current_dir_metadata = try!(current_dir_listing.get_sub_directories() + .iter() + .find(|a| *a.get_name() == *it) + .ok_or(LauncherError::PathNotFound)); try!(dir_helper.get(current_dir_metadata.get_key())) }; } diff --git a/src/launcher/parser/mod.rs b/src/launcher/parser/mod.rs index c127ab26..197bd267 100644 --- a/src/launcher/parser/mod.rs +++ b/src/launcher/parser/mod.rs @@ -15,84 +15,115 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. -pub type ResponseType = Result, ::errors::LauncherError>; +use std::fmt; +use std::sync::{Arc, Mutex}; + +use errors::LauncherError; +use safe_core::client::Client; +use safe_nfs::metadata::directory_key::DirectoryKey; + +pub type ResponseType = Result, LauncherError>; mod dns; mod nfs; mod traits; mod helper; -#[cfg(test)] mod test_utils; +#[cfg(test)]mod test_utils; #[derive(Clone)] pub struct ParameterPacket { - pub client : ::std::sync::Arc<::std::sync::Mutex<::safe_core::client::Client>>, - pub app_root_dir_key : ::safe_nfs::metadata::directory_key::DirectoryKey, - pub safe_drive_access : ::std::sync::Arc<::std::sync::Mutex>, - pub safe_drive_dir_key: ::safe_nfs::metadata::directory_key::DirectoryKey, + pub client: Arc>, + pub app_root_dir_key: DirectoryKey, + pub safe_drive_access: Arc>, + pub safe_drive_dir_key: DirectoryKey, } -pub fn begin_parse(params : ParameterPacket, - decoder: &mut D) -> ResponseType - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { - let endpoint: String = try!(parse_result!(decoder.read_struct_field("endpoint", - 0, - |d| ::rustc_serialize::Decodable::decode(d)), "")); +pub fn begin_parse(params: ParameterPacket, decoder: &mut D) -> ResponseType + where D: ::rustc_serialize::Decoder, + D::Error: fmt::Debug +{ + let endpoint: String = try!(parse_result!(decoder.read_struct_field("endpoint", 0, |d| { + ::rustc_serialize::Decodable::decode(d) + }), + "")); let mut tokens = helper::tokenise_path(&endpoint, true); tokens.reverse(); version_parser(params, tokens, decoder) } -fn version_parser(params : ParameterPacket, - mut endpoint_tokens: Vec, - decoder : &mut D) -> ResponseType - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { +fn version_parser(params: ParameterPacket, + mut endpoint_tokens: Vec, + decoder: &mut D) + -> ResponseType + where D: ::rustc_serialize::Decoder, + D::Error: fmt::Debug +{ let api_dest = try!(parse_option!(endpoint_tokens.pop(), "Invalid endpoint.")); if api_dest != "safe-api" { - return Err(::errors::LauncherError::SpecificParseError(format!("Unrecognised token \"{}\" in endpoint path.", api_dest))) + return Err(LauncherError::SpecificParseError(format!("Unrecognised token \"{}\" in \ + endpoint path.", + api_dest))); } - let mut version_str = try!(parse_option!(endpoint_tokens.pop(), "Invalid endpoint - Version token not found.")); + let mut version_str = try!(parse_option!(endpoint_tokens.pop(), + "Invalid endpoint - Version token not found.")); if version_str.len() < 4 || version_str.remove(0) != 'v' { - return Err(::errors::LauncherError::SpecificParseError("Unparsable version in endpoint path.".to_string())) + return Err(LauncherError::SpecificParseError("Unparsable version in endpoint path." + .to_string())); } let version = try!(parse_result!(version_str.parse::(), "Unparsable version")); module_dispatcher(params, endpoint_tokens, version, decoder) } -fn module_dispatcher(params : ParameterPacket, +fn module_dispatcher(params: ParameterPacket, mut remaining_tokens: Vec, - version : f32, - decoder : &mut D) -> ResponseType - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { - let module = try!(parse_option!(remaining_tokens.pop(), "Invalid endpoint - Module token not found.")); + version: f32, + decoder: &mut D) + -> ResponseType + where D: ::rustc_serialize::Decoder, + D::Error: fmt::Debug +{ + let module = try!(parse_option!(remaining_tokens.pop(), + "Invalid endpoint - Module token not found.")); match &module[..] { "nfs" => nfs::action_dispatcher(params, remaining_tokens, version, decoder), "dns" => dns::action_dispatcher(params, remaining_tokens, version, decoder), - _ => Err(::errors::LauncherError::SpecificParseError(format!("Unrecognised module \"{}\" in endpoint path.", module))), + _ => { + Err(LauncherError::SpecificParseError(format!("Unrecognised module \"{}\" in \ + endpoint path.", + module))) + } } } #[cfg(test)] mod test { + use rustc_serialize::json; + + use launcher::parser; + use launcher::parser::test_utils; + #[test] fn parse_request() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); let mut json_str = "{}"; - let mut json_obj = unwrap_result!(::rustc_serialize::json::Json::from_str(&json_str)); - assert!(::launcher::parser::begin_parse(parameter_packet.clone(), - &mut ::rustc_serialize::json::Decoder::new(json_obj)).is_err()); + let mut json_obj = unwrap_result!(json::Json::from_str(&json_str)); + assert!(parser::begin_parse(parameter_packet.clone(), &mut json::Decoder::new(json_obj)) + .is_err()); json_str = "{\"endpoint\": \"safe-api/v1.0/nfs/create-dir\", \"data\": {}}"; - json_obj = unwrap_result!(::rustc_serialize::json::Json::from_str(&json_str)); - assert!(::launcher::parser::begin_parse(parameter_packet.clone(), - &mut ::rustc_serialize::json::Decoder::new(json_obj)).is_err()); - - json_str = "{\"endpoint\": \"safe-api/v1.0/nfs/create-dir\", \"data\": {\"dir_path\": \"/demo\",\"is_path_shared\": false,\"is_private\": true,\"is_versioned\": false,\"user_metadata\": \"\"}}"; - json_obj = unwrap_result!(::rustc_serialize::json::Json::from_str(&json_str)); - assert!(::launcher::parser::begin_parse(parameter_packet.clone(), - &mut ::rustc_serialize::json::Decoder::new(json_obj)).is_ok()); + json_obj = unwrap_result!(json::Json::from_str(&json_str)); + assert!(parser::begin_parse(parameter_packet.clone(), &mut json::Decoder::new(json_obj)) + .is_err()); + + json_str = "{\"endpoint\": \"safe-api/v1.0/nfs/create-dir\", \"data\": {\"dir_path\": \ + \"/demo\",\"is_path_shared\": false,\"is_private\": true,\"is_versioned\": \ + false,\"user_metadata\": \"\"}}"; + json_obj = unwrap_result!(json::Json::from_str(&json_str)); + assert!(parser::begin_parse(parameter_packet.clone(), &mut json::Decoder::new(json_obj)) + .is_ok()); } } diff --git a/src/launcher/parser/nfs/create_dir_v1_0.rs b/src/launcher/parser/nfs/create_dir_v1_0.rs index 37b755b8..3a21be15 100644 --- a/src/launcher/parser/nfs/create_dir_v1_0.rs +++ b/src/launcher/parser/nfs/create_dir_v1_0.rs @@ -15,25 +15,30 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG, VERSIONED_DIRECTORY_LISTING_TAG}; +use safe_nfs::helper::directory_helper::DirectoryHelper; + #[derive(RustcDecodable, Debug)] pub struct CreateDir { - dir_path : String, - is_private : bool, - is_versioned : bool, - user_metadata : String, + dir_path: String, + is_private: bool, + is_versioned: bool, + user_metadata: String, is_path_shared: bool, } -impl ::launcher::parser::traits::Action for CreateDir { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for CreateDir { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { use rustc_serialize::base64::FromBase64; if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.dir_path, false); - let dir_to_create = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); + let mut tokens = helper::tokenise_path(&self.dir_path, false); + let dir_to_create = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); let start_dir_key = if self.is_path_shared { ¶ms.safe_drive_dir_key @@ -41,25 +46,26 @@ impl ::launcher::parser::traits::Action for CreateDir { ¶ms.app_root_dir_key }; - let mut parent_sub_dir = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let mut parent_sub_dir = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(params.client); + let dir_helper = DirectoryHelper::new(params.client); let access_level = if self.is_private { - ::safe_nfs::AccessLevel::Private + AccessLevel::Private } else { - ::safe_nfs::AccessLevel::Public + AccessLevel::Public }; let tag = if self.is_versioned { - ::safe_nfs::VERSIONED_DIRECTORY_LISTING_TAG + VERSIONED_DIRECTORY_LISTING_TAG } else { - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG + UNVERSIONED_DIRECTORY_LISTING_TAG }; - let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), "Faild Converting from Base64.")); + let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), + "Faild Converting from Base64.")); let _ = try!(dir_helper.create(dir_to_create, tag, @@ -75,17 +81,19 @@ impl ::launcher::parser::traits::Action for CreateDir { #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_nfs::helper::directory_helper::DirectoryHelper; #[test] fn create_dir() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); let mut request = CreateDir { - dir_path : "/".to_string(), - is_private : true, - is_versioned : false, - user_metadata : "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), + dir_path: "/".to_string(), + is_private: true, + is_versioned: false, + user_metadata: "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), is_path_shared: false, }; assert!(request.execute(parameter_packet.clone()).is_err()); @@ -102,13 +110,15 @@ mod test { request.dir_path = "/test_dir/secondlevel".to_string(); assert!(request.execute(parameter_packet.clone()).is_ok()); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client); + let dir_helper = DirectoryHelper::new(parameter_packet.client); let app_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); assert!(app_dir.find_sub_directory(&"test_dir".to_string()).is_some()); assert!(app_dir.find_sub_directory(&"test_dir2".to_string()).is_some()); assert_eq!(app_dir.get_sub_directories().len(), 2); - let test_dir_key = unwrap_option!(app_dir.find_sub_directory(&"test_dir".to_string()), "Directory not found").get_key(); + let test_dir_key = unwrap_option!(app_dir.find_sub_directory(&"test_dir".to_string()), + "Directory not found") + .get_key(); let test_dir = unwrap_result!(dir_helper.get(test_dir_key)); assert!(test_dir.find_sub_directory(&"secondlevel".to_string()).is_some()); } diff --git a/src/launcher/parser/nfs/create_file_v1_0.rs b/src/launcher/parser/nfs/create_file_v1_0.rs index 7e3c7c79..1cb63257 100644 --- a/src/launcher/parser/nfs/create_file_v1_0.rs +++ b/src/launcher/parser/nfs/create_file_v1_0.rs @@ -1,78 +1,83 @@ -// Copyright 2015 MaidSafe.net limited. -// -// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, -// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which -// licence you accepted on initial access to the Software (the "Licences"). -// -// By contributing code to the SAFE Network Software, or to this project generally, you agree to be -// bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the -// Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. -// -// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed -// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. -// -// Please review the Licences for the specific language governing permissions and limitations -// relating to use of the SAFE Network Software. - -#[derive(RustcDecodable, Debug)] -pub struct CreateFile { - file_path : String, - user_metadata : String, - is_path_shared: bool, -} - -impl ::launcher::parser::traits::Action for CreateFile { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { - use rustc_serialize::base64::FromBase64; - - if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) - }; - - let start_dir_key = if self.is_path_shared { - ¶ms.safe_drive_dir_key - } else { - ¶ms.app_root_dir_key - }; - - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.file_path, false); - let file_name = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); - - let file_directory = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); - - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(params.client); - let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), "Failed Converting from Base64.")); - - let writer = try!(file_helper.create(file_name, - bin_metadata, - file_directory)); - let _ = try!(writer.close()); - - Ok(None) - } -} - -#[cfg(test)] -mod test { - use super::*; - use ::launcher::parser::traits::Action; - - #[test] - fn create_file() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); - - let mut request = CreateFile { - file_path : "/test.txt".to_string(), - user_metadata : "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), - is_path_shared: false, - }; - assert!(request.execute(parameter_packet.clone()).is_ok()); - - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client); - let app_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); - assert!(app_dir.find_file(&"test.txt".to_string()).is_some()); - } -} +// Copyright 2015 MaidSafe.net limited. +// +// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License, +// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which +// licence you accepted on initial access to the Software (the "Licences"). +// +// By contributing code to the SAFE Network Software, or to this project generally, you agree to be +// bound by the terms of the MaidSafe Contributor Agreement, version 1.0. This, along with the +// Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR. +// +// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed +// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. +// +// Please review the Licences for the specific language governing permissions and limitations +// relating to use of the SAFE Network Software. + +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::helper::file_helper::FileHelper; + +#[derive(RustcDecodable, Debug)] +pub struct CreateFile { + file_path: String, + user_metadata: String, + is_path_shared: bool, +} + +impl traits::Action for CreateFile { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { + use rustc_serialize::base64::FromBase64; + + if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { + return Err(LauncherError::PermissionDenied); + }; + + let start_dir_key = if self.is_path_shared { + ¶ms.safe_drive_dir_key + } else { + ¶ms.app_root_dir_key + }; + + let mut tokens = helper::tokenise_path(&self.file_path, false); + let file_name = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); + + let file_directory = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); + + let file_helper = FileHelper::new(params.client); + let bin_metadata = try!(parse_result!(self.user_metadata.from_base64(), + "Failed Converting from Base64.")); + + let writer = try!(file_helper.create(file_name, bin_metadata, file_directory)); + let _ = try!(writer.close()); + + Ok(None) + } +} + +#[cfg(test)] +mod test { + use super::*; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_nfs::helper::directory_helper::DirectoryHelper; + + #[test] + fn create_file() { + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); + + let mut request = CreateFile { + file_path: "/test.txt".to_string(), + user_metadata: "InNhbXBsZSBtZXRhZGF0YSI=".to_string(), + is_path_shared: false, + }; + assert!(request.execute(parameter_packet.clone()).is_ok()); + + let dir_helper = DirectoryHelper::new(parameter_packet.client); + let app_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); + assert!(app_dir.find_file(&"test.txt".to_string()).is_some()); + } +} diff --git a/src/launcher/parser/nfs/delete_dir_v1_0.rs b/src/launcher/parser/nfs/delete_dir_v1_0.rs index 121e5826..149c0b4b 100644 --- a/src/launcher/parser/nfs/delete_dir_v1_0.rs +++ b/src/launcher/parser/nfs/delete_dir_v1_0.rs @@ -15,19 +15,22 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::helper::directory_helper::DirectoryHelper; + #[derive(RustcDecodable, Debug)] pub struct DeleteDir { - dir_path : String, + dir_path: String, is_path_shared: bool, } -impl ::launcher::parser::traits::Action for DeleteDir { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { - - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.dir_path, false); - let dir_to_delete = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); +impl traits::Action for DeleteDir { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { + let mut tokens = helper::tokenise_path(&self.dir_path, false); + let dir_to_delete = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(params.client); + let dir_helper = DirectoryHelper::new(params.client); let mut parent_dir = if self.is_path_shared { try!(dir_helper.get(¶ms.safe_drive_dir_key)) @@ -35,8 +38,7 @@ impl ::launcher::parser::traits::Action for DeleteDir { try!(dir_helper.get(¶ms.app_root_dir_key)) }; - let _ = try!(dir_helper.delete(&mut parent_dir, - &dir_to_delete)); + let _ = try!(dir_helper.delete(&mut parent_dir, &dir_to_delete)); Ok(None) } @@ -45,24 +47,27 @@ impl ::launcher::parser::traits::Action for DeleteDir { #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; + use safe_nfs::helper::directory_helper::DirectoryHelper; #[test] fn delete_dir() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let _ = unwrap_result!(dir_helper.create("test_dir".to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, - Vec::new(), - false, - ::safe_nfs::AccessLevel::Private, - Some(&mut app_root_dir))); + UNVERSIONED_DIRECTORY_LISTING_TAG, + Vec::new(), + false, + AccessLevel::Private, + Some(&mut app_root_dir))); let mut request = DeleteDir { - dir_path : "/test_dir2".to_string(), + dir_path: "/test_dir2".to_string(), is_path_shared: false, }; assert!(request.execute(parameter_packet.clone()).is_err()); diff --git a/src/launcher/parser/nfs/delete_file_v1_0.rs b/src/launcher/parser/nfs/delete_file_v1_0.rs index 53dc563f..ce15f6a0 100644 --- a/src/launcher/parser/nfs/delete_file_v1_0.rs +++ b/src/launcher/parser/nfs/delete_file_v1_0.rs @@ -15,30 +15,32 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::helper::file_helper::FileHelper; + #[derive(RustcDecodable, Debug)] pub struct DeleteFile { - file_path : String, + file_path: String, is_path_shared: bool, } -impl ::launcher::parser::traits::Action for DeleteFile { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { - +impl traits::Action for DeleteFile { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { let start_dir_key = if self.is_path_shared { ¶ms.safe_drive_dir_key } else { ¶ms.app_root_dir_key }; - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.file_path, false); - let file_name = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); - let mut dir_of_file = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let mut tokens = helper::tokenise_path(&self.file_path, false); + let file_name = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); + let mut dir_of_file = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(params.client); - let _ = try!(file_helper.delete(file_name, - &mut dir_of_file)); + let file_helper = FileHelper::new(params.client); + let _ = try!(file_helper.delete(file_name, &mut dir_of_file)); Ok(None) } @@ -48,22 +50,25 @@ impl ::launcher::parser::traits::Action for DeleteFile { #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; + use safe_nfs::helper::file_helper::FileHelper; + use safe_nfs::helper::directory_helper::DirectoryHelper; #[test] fn delete_file() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(parameter_packet.client.clone()); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let file_helper = FileHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let writer = unwrap_result!(file_helper.create("test_file.txt".to_string(), - Vec::new(), - app_root_dir)); + Vec::new(), + app_root_dir)); let _ = unwrap_result!(writer.close()); let mut request = DeleteFile { - file_path : "/test_file.txt".to_string(), + file_path: "/test_file.txt".to_string(), is_path_shared: false, }; diff --git a/src/launcher/parser/nfs/get_dir_v1_0.rs b/src/launcher/parser/nfs/get_dir_v1_0.rs index 021ce171..4a16ed35 100644 --- a/src/launcher/parser/nfs/get_dir_v1_0.rs +++ b/src/launcher/parser/nfs/get_dir_v1_0.rs @@ -15,17 +15,22 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::metadata::directory_metadata::DirectoryMetadata; +use safe_nfs::metadata::file_metadata::FileMetadata; + #[derive(RustcDecodable, Debug)] pub struct GetDir { - dir_path : String, - timeout_ms : i64, + dir_path: String, + timeout_ms: i64, is_path_shared: bool, } -impl ::launcher::parser::traits::Action for GetDir { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for GetDir { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } let start_dir_key = if self.is_path_shared { @@ -34,12 +39,13 @@ impl ::launcher::parser::traits::Action for GetDir { ¶ms.app_root_dir_key }; - let tokens = ::launcher::parser::helper::tokenise_path(&self.dir_path, false); - let dir_fetched = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let tokens = helper::tokenise_path(&self.dir_path, false); + let dir_fetched = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); let dir_info = get_directory_info(dir_fetched.get_metadata()); - let mut sub_dirs: Vec = Vec::with_capacity(dir_fetched.get_sub_directories().len()); + let mut sub_dirs: Vec = + Vec::with_capacity(dir_fetched.get_sub_directories().len()); for metadata in dir_fetched.get_sub_directories() { sub_dirs.push(get_directory_info(metadata)); } @@ -50,8 +56,8 @@ impl ::launcher::parser::traits::Action for GetDir { } let response = GetDirResponse { - info : dir_info, - files : files, + info: dir_info, + files: files, sub_directories: sub_dirs, }; @@ -59,97 +65,102 @@ impl ::launcher::parser::traits::Action for GetDir { } } -fn get_directory_info(dir_metadata: &::safe_nfs::metadata::directory_metadata::DirectoryMetadata) -> DirectoryInfo { +fn get_directory_info(dir_metadata: &DirectoryMetadata) -> DirectoryInfo { use rustc_serialize::base64::ToBase64; let dir_key = dir_metadata.get_key(); let created_time = dir_metadata.get_created_time().to_timespec(); let modified_time = dir_metadata.get_modified_time().to_timespec(); DirectoryInfo { - name : dir_metadata.get_name().clone(), - is_private : *dir_key.get_access_level() == ::safe_nfs::AccessLevel::Private, - is_versioned : dir_key.is_versioned(), - user_metadata : (*dir_metadata.get_user_metadata()).to_base64(::config::get_base64_config()), - creation_time_sec : created_time.sec, - creation_time_nsec : created_time.nsec as i64, - modification_time_sec : modified_time.sec, + name: dir_metadata.get_name().clone(), + is_private: *dir_key.get_access_level() == ::safe_nfs::AccessLevel::Private, + is_versioned: dir_key.is_versioned(), + user_metadata: (*dir_metadata.get_user_metadata()) + .to_base64(::config::get_base64_config()), + creation_time_sec: created_time.sec, + creation_time_nsec: created_time.nsec as i64, + modification_time_sec: modified_time.sec, modification_time_nsec: modified_time.nsec as i64, } } -fn get_file_info(file_metadata: &::safe_nfs::metadata::file_metadata::FileMetadata) -> FileInfo { +fn get_file_info(file_metadata: &FileMetadata) -> FileInfo { use rustc_serialize::base64::ToBase64; let created_time = file_metadata.get_created_time().to_timespec(); let modified_time = file_metadata.get_modified_time().to_timespec(); FileInfo { - name : file_metadata.get_name().clone(), - size : file_metadata.get_size() as i64, - user_metadata : (*file_metadata.get_user_metadata()).to_base64(::config::get_base64_config()), - creation_time_sec : created_time.sec, - creation_time_nsec : created_time.nsec as i64, - modification_time_sec : modified_time.sec, + name: file_metadata.get_name().clone(), + size: file_metadata.get_size() as i64, + user_metadata: (*file_metadata.get_user_metadata()) + .to_base64(::config::get_base64_config()), + creation_time_sec: created_time.sec, + creation_time_nsec: created_time.nsec as i64, + modification_time_sec: modified_time.sec, modification_time_nsec: modified_time.nsec as i64, } } #[derive(RustcEncodable, Debug)] struct GetDirResponse { - info : DirectoryInfo, - files : Vec, + info: DirectoryInfo, + files: Vec, sub_directories: Vec, } #[derive(RustcEncodable, Debug)] struct DirectoryInfo { - name : String, - is_private : bool, - is_versioned : bool, - user_metadata : String, - creation_time_sec : i64, - creation_time_nsec : i64, - modification_time_sec : i64, + name: String, + is_private: bool, + is_versioned: bool, + user_metadata: String, + creation_time_sec: i64, + creation_time_nsec: i64, + modification_time_sec: i64, modification_time_nsec: i64, } #[derive(RustcEncodable, Debug)] struct FileInfo { - name : String, - size : i64, - user_metadata : String, - creation_time_sec : i64, - creation_time_nsec : i64, - modification_time_sec : i64, + name: String, + size: i64, + user_metadata: String, + creation_time_sec: i64, + creation_time_nsec: i64, + modification_time_sec: i64, modification_time_nsec: i64, } #[cfg(test)] mod test { - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::{ParameterPacket, test_utils}; + use safe_nfs::helper::directory_helper::DirectoryHelper; + use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; const TEST_DIR_NAME: &'static str = "test_dir"; - fn create_test_dir(parameter_packet: &::launcher::parser::ParameterPacket) { - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + fn create_test_dir(parameter_packet: &ParameterPacket) { + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, - Vec::new(), - false, - ::safe_nfs::AccessLevel::Private, - Some(&mut app_root_dir))); + UNVERSIONED_DIRECTORY_LISTING_TAG, + Vec::new(), + false, + AccessLevel::Private, + Some(&mut app_root_dir))); } #[test] fn get_dir() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_dir(¶meter_packet); let mut request = super::GetDir { - dir_path : format!("/{}", TEST_DIR_NAME), - timeout_ms : 1000, + dir_path: format!("/{}", TEST_DIR_NAME), + timeout_ms: 1000, is_path_shared: false, }; diff --git a/src/launcher/parser/nfs/get_file_v1_0.rs b/src/launcher/parser/nfs/get_file_v1_0.rs index 977aac75..5f7dc572 100644 --- a/src/launcher/parser/nfs/get_file_v1_0.rs +++ b/src/launcher/parser/nfs/get_file_v1_0.rs @@ -17,26 +17,35 @@ // TODO(Spanda) needs a get timeout - Modify Rfc +use std::collections::BTreeMap; + +use rustc_serialize::json; + +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::helper::file_helper::FileHelper; +use safe_nfs::metadata::file_metadata::FileMetadata; + #[derive(RustcDecodable, Debug)] pub struct GetFile { - offset : i64, - length : i64, - file_path : String, - is_path_shared : bool, + offset: i64, + length: i64, + file_path: String, + is_path_shared: bool, include_metadata: bool, } -impl ::launcher::parser::traits::Action for GetFile { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for GetFile { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { use rustc_serialize::json::ToJson; use rustc_serialize::base64::ToBase64; if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.file_path, false); - let file_name = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); + let mut tokens = helper::tokenise_path(&self.file_path, false); + let file_name = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); let start_dir_key = if self.is_path_shared { ¶ms.safe_drive_dir_key @@ -44,10 +53,11 @@ impl ::launcher::parser::traits::Action for GetFile { ¶ms.app_root_dir_key }; - let file_dir = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); - let file = try!(file_dir.find_file(&file_name).ok_or(::errors::LauncherError::InvalidPath)); + let file_dir = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); + let file = try!(file_dir.find_file(&file_name) + .ok_or(::errors::LauncherError::InvalidPath)); let file_metadata = if self.include_metadata { Some(get_file_metadata(file.get_metadata())) @@ -55,7 +65,7 @@ impl ::launcher::parser::traits::Action for GetFile { None }; - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(params.client); + let file_helper = FileHelper::new(params.client); let mut reader = file_helper.read(&file); // TODO(Krishna) This is WRONG - see rfc. let mut size = self.length as u64; @@ -63,73 +73,78 @@ impl ::launcher::parser::traits::Action for GetFile { size = reader.size(); }; let response = GetFileResponse { - content : try!(reader.read(self.offset as u64, size)).to_base64(::config::get_base64_config()), + content: try!(reader.read(self.offset as u64, size)) + .to_base64(::config::get_base64_config()), metadata: file_metadata, }; - Ok(Some(try!(::rustc_serialize::json::encode(&response.to_json())))) + Ok(Some(try!(json::encode(&response.to_json())))) } } -fn get_file_metadata(file_metadata: &::safe_nfs::metadata::file_metadata::FileMetadata) -> Metadata { +fn get_file_metadata(file_metadata: &FileMetadata) -> Metadata { use rustc_serialize::base64::ToBase64; let created_time = file_metadata.get_created_time().to_timespec(); let modified_time = file_metadata.get_modified_time().to_timespec(); Metadata { - name : file_metadata.get_name().clone(), - size : file_metadata.get_size() as i64, - user_metadata : (*file_metadata.get_user_metadata()).to_base64(::config::get_base64_config()), - creation_time_sec : created_time.sec, - creation_time_nsec : created_time.nsec as i64, - modification_time_sec : modified_time.sec, + name: file_metadata.get_name().clone(), + size: file_metadata.get_size() as i64, + user_metadata: (*file_metadata.get_user_metadata()) + .to_base64(::config::get_base64_config()), + creation_time_sec: created_time.sec, + creation_time_nsec: created_time.nsec as i64, + modification_time_sec: modified_time.sec, modification_time_nsec: modified_time.nsec as i64, } } #[derive(Debug)] struct GetFileResponse { - content : String, + content: String, metadata: Option, } -impl ::rustc_serialize::json::ToJson for GetFileResponse { - fn to_json(&self) -> ::rustc_serialize::json::Json { - let mut response_tree = ::std::collections::BTreeMap::new(); +impl json::ToJson for GetFileResponse { + fn to_json(&self) -> json::Json { + let mut response_tree = BTreeMap::new(); let _ = response_tree.insert("content".to_string(), self.content.to_json()); if let Some(ref metadata) = self.metadata { - let json_metadata_str = unwrap_result!(::rustc_serialize::json::encode(metadata)); + let json_metadata_str = unwrap_result!(json::encode(metadata)); let _ = response_tree.insert("metadata".to_string(), json_metadata_str.to_json()); } - ::rustc_serialize::json::Json::Object(response_tree) + json::Json::Object(response_tree) } } #[derive(RustcEncodable, Debug)] struct Metadata { - name : String, - size : i64, - user_metadata : String, - creation_time_sec : i64, - creation_time_nsec : i64, - modification_time_sec : i64, + name: String, + size: i64, + user_metadata: String, + creation_time_sec: i64, + creation_time_nsec: i64, + modification_time_sec: i64, modification_time_nsec: i64, } #[cfg(test)] mod test { - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::{ParameterPacket, test_utils}; + use safe_nfs::helper::file_helper::FileHelper; + use safe_nfs::helper::directory_helper::DirectoryHelper; const TEST_FILE_NAME: &'static str = "test_file.txt"; - fn create_test_file(parameter_packet: &::launcher::parser::ParameterPacket) { - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(parameter_packet.client.clone()); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + fn create_test_file(parameter_packet: &ParameterPacket) { + let file_helper = FileHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let mut writer = unwrap_result!(file_helper.create(TEST_FILE_NAME.to_string(), - Vec::new(), - app_root_dir)); + Vec::new(), + app_root_dir)); let data = vec![10u8; 20]; writer.write(&data[..], 0); let _ = unwrap_result!(writer.close()); @@ -138,15 +153,15 @@ mod test { #[test] fn get_file() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_file(¶meter_packet); let mut request = super::GetFile { - offset : 0, - length : 0, - file_path : format!("/{}", TEST_FILE_NAME), - is_path_shared : false, + offset: 0, + length: 0, + file_path: format!("/{}", TEST_FILE_NAME), + is_path_shared: false, include_metadata: true, }; diff --git a/src/launcher/parser/nfs/mod.rs b/src/launcher/parser/nfs/mod.rs index ba9320af..61a06362 100644 --- a/src/launcher/parser/nfs/mod.rs +++ b/src/launcher/parser/nfs/mod.rs @@ -24,61 +24,136 @@ mod create_file_v1_0; mod delete_file_v1_0; mod modify_file_v1_0; -pub fn action_dispatcher(params : ::launcher::parser::ParameterPacket, +use errors::LauncherError; +use launcher::parser::{ParameterPacket, ResponseType, traits}; + +pub fn action_dispatcher(params: ParameterPacket, mut remaining_tokens: Vec, - version : f32, - decoder : &mut D) -> ::launcher::parser::ResponseType - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { + version: f32, + decoder: &mut D) + -> ResponseType + where D: ::rustc_serialize::Decoder, + D::Error: ::std::fmt::Debug +{ if remaining_tokens.len() > 1 { - return Err(::errors::LauncherError::SpecificParseError("Extra unrecognised tokens in endpoint.".to_string())) + return Err(LauncherError::SpecificParseError("Extra unrecognised tokens in endpoint." + .to_string())); } - let action_str = try!(parse_option!(remaining_tokens.pop(), "Invalid endpoint - Action not found.")); + let action_str = try!(parse_option!(remaining_tokens.pop(), + "Invalid endpoint - Action not found.")); let mut action = try!(get_action(&action_str, version, decoder)); action.execute(params) } -fn get_action(action_str: &str, version: f32, decoder: &mut D) -> Result, ::errors::LauncherError> - where D: ::rustc_serialize::Decoder, D::Error: ::std::fmt::Debug { +fn get_action(action_str: &str, + version: f32, + decoder: &mut D) + -> Result, LauncherError> + where D: ::rustc_serialize::Decoder, + D::Error: ::std::fmt::Debug +{ use rustc_serialize::Decodable; - let version_err = Err(::errors::LauncherError::SpecificParseError(format!("Unsupported version {:?} for this endpoint.", version))); + let version_err = Err(LauncherError::SpecificParseError(format!("Unsupported version {:?} \ + for this endpoint.", + version))); Ok(match action_str { - "create-dir" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| create_dir_v1_0::CreateDir::decode(d)), ""))), - _ => return version_err, - }, - "delete-dir" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| delete_dir_v1_0::DeleteDir::decode(d)), ""))), - _ => return version_err, - }, - "modify-dir" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| modify_dir_v1_0::ModifyDir::decode(d)), ""))), - _ => return version_err, - }, - "get-dir" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| get_dir_v1_0::GetDir::decode(d)), ""))), - _ => return version_err, - }, - "create-file" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| create_file_v1_0::CreateFile::decode(d)), ""))), - _ => return version_err, - }, - "delete-file" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| delete_file_v1_0::DeleteFile::decode(d)), ""))), - _ => return version_err, - }, - "modify-file" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| modify_file_v1_0::ModifyFile::decode(d)), ""))), - _ => return version_err, - }, - "get-file" => match version { - 1.0 => Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| get_file_v1_0::GetFile::decode(d)), ""))), - _ => return version_err, - }, - _ => return Err(::errors::LauncherError::SpecificParseError(format!("Unsupported action {:?} for this endpoint.", action_str))), + "create-dir" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + create_dir_v1_0::CreateDir::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "delete-dir" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + delete_dir_v1_0::DeleteDir::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "modify-dir" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + modify_dir_v1_0::ModifyDir::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "get-dir" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + get_dir_v1_0::GetDir::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "create-file" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + create_file_v1_0::CreateFile::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "delete-file" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + delete_file_v1_0::DeleteFile::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "modify-file" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + modify_file_v1_0::ModifyFile::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + "get-file" => { + match version { + 1.0 => { + Box::new(try!(parse_result!(decoder.read_struct_field("data", 0, |d| { + get_file_v1_0::GetFile::decode(d) + }), + ""))) + } + _ => return version_err, + } + } + _ => { + return Err(LauncherError::SpecificParseError(format!("Unsupported action {:?} for \ + this endpoint.", + action_str))) + } }) } diff --git a/src/launcher/parser/nfs/modify_dir_v1_0.rs b/src/launcher/parser/nfs/modify_dir_v1_0.rs index cf401730..0ecad624 100644 --- a/src/launcher/parser/nfs/modify_dir_v1_0.rs +++ b/src/launcher/parser/nfs/modify_dir_v1_0.rs @@ -15,23 +15,27 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType}; +use safe_nfs::helper::directory_helper::DirectoryHelper; + #[derive(RustcDecodable, Debug)] pub struct ModifyDir { - dir_path : String, - new_values : OptionalParams, + dir_path: String, + new_values: OptionalParams, is_path_shared: bool, } impl ::launcher::parser::traits::Action for ModifyDir { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { use rustc_serialize::base64::FromBase64; if !(self.new_values.name.is_some() || self.new_values.user_metadata.is_some()) { - return Err(::errors::LauncherError::from("Optional parameters could not be parsed")); + return Err(LauncherError::from("Optional parameters could not be parsed")); } if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } let start_dir_key = if self.is_path_shared { @@ -40,18 +44,19 @@ impl ::launcher::parser::traits::Action for ModifyDir { ¶ms.app_root_dir_key }; - let tokens = ::launcher::parser::helper::tokenise_path(&self.dir_path, false); - let mut dir_to_modify = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let tokens = helper::tokenise_path(&self.dir_path, false); + let mut dir_to_modify = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let directory_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(params.client); + let directory_helper = DirectoryHelper::new(params.client); if let Some(ref name) = self.new_values.name { dir_to_modify.get_mut_metadata().set_name(name.clone()); } if let Some(ref metadata_base64) = self.new_values.user_metadata { - let metadata = try!(parse_result!(metadata_base64.from_base64(), "Failed to convert from base64")); + let metadata = try!(parse_result!(metadata_base64.from_base64(), + "Failed to convert from base64")); dir_to_modify.get_mut_metadata().set_user_metadata(metadata); } @@ -63,48 +68,51 @@ impl ::launcher::parser::traits::Action for ModifyDir { #[derive(Debug, RustcDecodable)] struct OptionalParams { - pub name : Option, + pub name: Option, pub user_metadata: Option, } #[cfg(test)] mod test { use super::*; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::{ParameterPacket, test_utils}; use rustc_serialize::base64::ToBase64; + use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; + use safe_nfs::helper::directory_helper::DirectoryHelper; const TEST_DIR_NAME: &'static str = "test_dir"; const METADATA_BASE64: &'static str = "c2FtcGxlIHRleHQ="; - fn create_test_dir(parameter_packet: &::launcher::parser::ParameterPacket) { - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + fn create_test_dir(parameter_packet: &ParameterPacket) { + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); let _ = unwrap_result!(dir_helper.create(TEST_DIR_NAME.to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, - Vec::new(), - false, - ::safe_nfs::AccessLevel::Private, - Some(&mut app_root_dir))); + UNVERSIONED_DIRECTORY_LISTING_TAG, + Vec::new(), + false, + AccessLevel::Private, + Some(&mut app_root_dir))); } #[test] fn rename_dir() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_dir(¶meter_packet); let values = super::OptionalParams { - name : Some("new_test_dir".to_string()), - user_metadata: None + name: Some("new_test_dir".to_string()), + user_metadata: None, }; let mut request = ModifyDir { - dir_path : format!("/{}", TEST_DIR_NAME), - new_values : values, + dir_path: format!("/{}", TEST_DIR_NAME), + new_values: values, is_path_shared: false, }; - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); assert_eq!(app_root_dir.get_sub_directories().len(), 1); assert!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()).is_some()); @@ -118,29 +126,36 @@ mod test { #[test] fn dir_update_user_metadata() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_dir(¶meter_packet); let values = super::OptionalParams { - name : None, + name: None, user_metadata: Some(METADATA_BASE64.to_string()), }; let mut request = ModifyDir { - dir_path : format!("/{}", TEST_DIR_NAME), - new_values : values, + dir_path: format!("/{}", TEST_DIR_NAME), + new_values: values, is_path_shared: false, }; - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); - let directory_key = unwrap_option!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()), "Directory not found").get_key(); + let directory_key = + unwrap_option!(app_root_dir.find_sub_directory(&TEST_DIR_NAME.to_string()), + "Directory not found") + .get_key(); let mut directory_to_modify = unwrap_result!(dir_helper.get(directory_key)); - assert_eq!(directory_to_modify.get_metadata().get_user_metadata().len(), 0); + assert_eq!(directory_to_modify.get_metadata().get_user_metadata().len(), + 0); assert!(request.execute(parameter_packet).is_ok()); directory_to_modify = unwrap_result!(dir_helper.get(directory_key)); assert!(directory_to_modify.get_metadata().get_user_metadata().len() > 0); - assert_eq!(directory_to_modify.get_metadata().get_user_metadata().to_base64(::config::get_base64_config()), METADATA_BASE64.to_string()); + assert_eq!(directory_to_modify.get_metadata() + .get_user_metadata() + .to_base64(::config::get_base64_config()), + METADATA_BASE64.to_string()); } } diff --git a/src/launcher/parser/nfs/modify_file_v1_0.rs b/src/launcher/parser/nfs/modify_file_v1_0.rs index a6da69ff..d384ac7a 100644 --- a/src/launcher/parser/nfs/modify_file_v1_0.rs +++ b/src/launcher/parser/nfs/modify_file_v1_0.rs @@ -15,25 +15,29 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. +use errors::LauncherError; +use launcher::parser::{helper, ParameterPacket, ResponseType, traits}; +use safe_nfs::helper::file_helper::FileHelper; +use safe_nfs::helper::writer::Mode; + #[derive(RustcDecodable, Debug)] pub struct ModifyFile { - file_path : String, - new_values : OptionalParams, + file_path: String, + new_values: OptionalParams, is_path_shared: bool, } -impl ::launcher::parser::traits::Action for ModifyFile { - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType { +impl traits::Action for ModifyFile { + fn execute(&mut self, params: ParameterPacket) -> ResponseType { use rustc_serialize::base64::FromBase64; if self.is_path_shared && !*unwrap_result!(params.safe_drive_access.lock()) { - return Err(::errors::LauncherError::PermissionDenied) + return Err(LauncherError::PermissionDenied); } - if self.new_values.name.is_none() && - self.new_values.user_metadata.is_none() && + if self.new_values.name.is_none() && self.new_values.user_metadata.is_none() && self.new_values.content.is_none() { - return Err(::errors::LauncherError::from("Optional parameters could not be parsed")); + return Err(LauncherError::from("Optional parameters could not be parsed")); } let start_dir_key = if self.is_path_shared { @@ -42,15 +46,17 @@ impl ::launcher::parser::traits::Action for ModifyFile { ¶ms.app_root_dir_key }; - let mut tokens = ::launcher::parser::helper::tokenise_path(&self.file_path, false); - let file_name = try!(tokens.pop().ok_or(::errors::LauncherError::InvalidPath)); - let mut dir_of_file = try!(::launcher::parser::helper::get_final_subdirectory(params.client.clone(), - &tokens, - Some(start_dir_key))); + let mut tokens = helper::tokenise_path(&self.file_path, false); + let file_name = try!(tokens.pop().ok_or(LauncherError::InvalidPath)); + let mut dir_of_file = try!(helper::get_final_subdirectory(params.client.clone(), + &tokens, + Some(start_dir_key))); - let mut file = try!(dir_of_file.find_file(&file_name).map(|file| file.clone()).ok_or(::errors::LauncherError::InvalidPath)); + let mut file = try!(dir_of_file.find_file(&file_name) + .map(|file| file.clone()) + .ok_or(LauncherError::InvalidPath)); - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(params.client); + let file_helper = FileHelper::new(params.client); let mut metadata_updated = false; if let Some(ref name) = self.new_values.name { @@ -59,7 +65,8 @@ impl ::launcher::parser::traits::Action for ModifyFile { } if let Some(ref metadata_base64) = self.new_values.user_metadata { - let metadata = try!(parse_result!(metadata_base64.from_base64(), "Failed to convert from base64")); + let metadata = try!(parse_result!(metadata_base64.from_base64(), + "Failed to convert from base64")); file.get_mut_metadata().set_user_metadata(metadata); metadata_updated = true; } @@ -70,11 +77,12 @@ impl ::launcher::parser::traits::Action for ModifyFile { if let Some(ref file_content_params) = self.new_values.content { let (mode, offset) = match file_content_params.offset { - Some(offset) => (::safe_nfs::helper::writer::Mode::Modify, offset), - None => (::safe_nfs::helper::writer::Mode::Overwrite, 0), + Some(offset) => (Mode::Modify, offset), + None => (Mode::Overwrite, 0), }; let mut writer = try!(file_helper.update_content(file.clone(), mode, dir_of_file)); - let bytes = try!(parse_result!(file_content_params.bytes.from_base64(), "Failed to convert from base64")); + let bytes = try!(parse_result!(file_content_params.bytes.from_base64(), + "Failed to convert from base64")); writer.write(&bytes[..], offset); let _ = try!(writer.close()); } @@ -85,53 +93,59 @@ impl ::launcher::parser::traits::Action for ModifyFile { #[derive(RustcDecodable, Debug)] struct OptionalParams { - pub name : Option, - pub content : Option, + pub name: Option, + pub content: Option, pub user_metadata: Option, } #[derive(RustcDecodable, Debug)] struct FileContentParams { - pub bytes : String, - pub offset: Option + pub bytes: String, + pub offset: Option, } #[cfg(test)] mod test { use super::{ModifyFile, FileContentParams, OptionalParams}; - use ::launcher::parser::traits::Action; + use launcher::parser::traits::Action; + use launcher::parser::test_utils; use rustc_serialize::base64::ToBase64; + use launcher::parser::ParameterPacket; + use safe_nfs::helper::directory_helper::DirectoryHelper; + use safe_nfs::helper::file_helper::FileHelper; const TEST_FILE_NAME: &'static str = "test_file.txt"; const METADATA_BASE64: &'static str = "c2FtcGxlIHRleHQ="; - fn create_test_file(parameter_packet: &::launcher::parser::ParameterPacket) { - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(parameter_packet.client.clone()); - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + fn create_test_file(parameter_packet: &ParameterPacket) { + let file_helper = FileHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); - let writer = unwrap_result!(file_helper.create(TEST_FILE_NAME.to_string(), Vec::new(), app_root_dir)); + let writer = unwrap_result!(file_helper.create(TEST_FILE_NAME.to_string(), + Vec::new(), + app_root_dir)); let _ = unwrap_result!(writer.close()); } #[test] fn file_rename() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_file(¶meter_packet); let values = OptionalParams { - name : Some("new_test_file.txt".to_string()), - content : None, - user_metadata: None + name: Some("new_test_file.txt".to_string()), + content: None, + user_metadata: None, }; let mut request = ModifyFile { - file_path : format!("/{}", TEST_FILE_NAME), - new_values : values, + file_path: format!("/{}", TEST_FILE_NAME), + new_values: values, is_path_shared: false, }; - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let mut app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); assert_eq!(app_root_dir.get_files().len(), 1); assert!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()).is_some()); @@ -145,72 +159,81 @@ mod test { #[test] fn file_update_user_metadata() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_file(¶meter_packet); let values = OptionalParams { - name : None, - content : None, + name: None, + content: None, user_metadata: Some(METADATA_BASE64.to_string()), }; let mut request = ModifyFile { - file_path : format!("/{}", TEST_FILE_NAME), - new_values : values, + file_path: format!("/{}", TEST_FILE_NAME), + new_values: values, is_path_shared: false, }; - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); - let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), "File not found"); + let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), + "File not found"); assert_eq!(file.get_metadata().get_user_metadata().len(), 0); let app_root_dir_key = parameter_packet.app_root_dir_key.clone(); assert!(request.execute(parameter_packet).is_ok()); let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); - let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), "File not found"); + let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), + "File not found"); assert!(file.get_metadata().get_user_metadata().len() > 0); - assert_eq!(file.get_metadata().get_user_metadata().to_base64(::config::get_base64_config()), METADATA_BASE64.to_string()); + assert_eq!(file.get_metadata() + .get_user_metadata() + .to_base64(::config::get_base64_config()), + METADATA_BASE64.to_string()); } #[test] fn file_update_content() { - let parameter_packet = unwrap_result!(::launcher::parser::test_utils::get_parameter_packet(false)); + let parameter_packet = unwrap_result!(test_utils::get_parameter_packet(false)); create_test_file(¶meter_packet); let content = FileContentParams { - bytes : METADATA_BASE64.to_string(), + bytes: METADATA_BASE64.to_string(), offset: None, }; let values = OptionalParams { - name : None, - content : Some(content), + name: None, + content: Some(content), user_metadata: None, }; let mut request = ModifyFile { - file_path : format!("/{}", TEST_FILE_NAME), - new_values : values, + file_path: format!("/{}", TEST_FILE_NAME), + new_values: values, is_path_shared: false, }; - let dir_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(parameter_packet.client.clone()); + let dir_helper = DirectoryHelper::new(parameter_packet.client.clone()); let app_root_dir = unwrap_result!(dir_helper.get(¶meter_packet.app_root_dir_key)); - let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), "File not found"); + let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), + "File not found"); assert_eq!(file.get_metadata().get_size(), 0); let app_root_dir_key = parameter_packet.app_root_dir_key.clone(); assert!(request.execute(parameter_packet.clone()).is_ok()); let app_root_dir = unwrap_result!(dir_helper.get(&app_root_dir_key)); - let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), "File not found"); + let file = unwrap_option!(app_root_dir.find_file(&TEST_FILE_NAME.to_string()), + "File not found"); let file_size = file.get_metadata().get_size(); assert!(file_size > 0); - let file_helper = ::safe_nfs::helper::file_helper::FileHelper::new(parameter_packet.client.clone()); + let file_helper = + ::safe_nfs::helper::file_helper::FileHelper::new(parameter_packet.client.clone()); let mut reader = file_helper.read(file); let size = reader.size(); assert_eq!(size, file_size); let data = unwrap_result!(reader.read(0, size)); - assert_eq!(data.to_base64(::config::get_base64_config()), METADATA_BASE64.to_string()); + assert_eq!(data.to_base64(::config::get_base64_config()), + METADATA_BASE64.to_string()); } } diff --git a/src/launcher/parser/test_utils.rs b/src/launcher/parser/test_utils.rs index 032a83cf..0fbf9d29 100644 --- a/src/launcher/parser/test_utils.rs +++ b/src/launcher/parser/test_utils.rs @@ -15,26 +15,34 @@ // Please review the Licences for the specific language governing permissions and limitations // relating to use of the SAFE Network Software. -pub fn get_parameter_packet(has_safe_drive_access: bool) -> Result<::launcher::parser::ParameterPacket, ::errors::LauncherError> { - let client = ::std::sync::Arc::new(::std::sync::Mutex::new(try!(::safe_core::utility::test_utils::get_client()))); - let directory_helper = ::safe_nfs::helper::directory_helper::DirectoryHelper::new(client.clone()); +use std::sync::{Arc, Mutex}; + +use errors::LauncherError; +use launcher::parser::ParameterPacket; +use safe_core::utility::test_utils; +use safe_nfs::helper::directory_helper::DirectoryHelper; +use safe_nfs::{AccessLevel, UNVERSIONED_DIRECTORY_LISTING_TAG}; + +pub fn get_parameter_packet(has_safe_drive_access: bool) -> Result { + let client = Arc::new(Mutex::new(try!(test_utils::get_client()))); + let directory_helper = DirectoryHelper::new(client.clone()); let mut user_root_dir = try!(directory_helper.get_user_root_directory_listing()); let (safe_drive, _) = try!(directory_helper.create(::config::SAFE_DRIVE_DIR_NAME.to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, + UNVERSIONED_DIRECTORY_LISTING_TAG, Vec::new(), false, - ::safe_nfs::AccessLevel::Private, + AccessLevel::Private, Some(&mut user_root_dir))); let (test_app, _) = try!(directory_helper.create("Test_Application".to_string(), - ::safe_nfs::UNVERSIONED_DIRECTORY_LISTING_TAG, + UNVERSIONED_DIRECTORY_LISTING_TAG, Vec::new(), false, - ::safe_nfs::AccessLevel::Private, + AccessLevel::Private, Some(&mut user_root_dir))); - Ok(::launcher::parser::ParameterPacket { - client : client, - app_root_dir_key : test_app.get_key().clone(), - safe_drive_access : ::std::sync::Arc::new(::std::sync::Mutex::new(has_safe_drive_access)), + Ok(ParameterPacket { + client: client, + app_root_dir_key: test_app.get_key().clone(), + safe_drive_access: Arc::new(Mutex::new(has_safe_drive_access)), safe_drive_dir_key: safe_drive.get_key().clone(), }) } diff --git a/src/launcher/parser/traits.rs b/src/launcher/parser/traits.rs index 9456f88b..fe9313df 100644 --- a/src/launcher/parser/traits.rs +++ b/src/launcher/parser/traits.rs @@ -18,5 +18,7 @@ /// ICommand trait pub trait Action { /// ICommand executer - fn execute(&mut self, params: ::launcher::parser::ParameterPacket) -> ::launcher::parser::ResponseType; + fn execute(&mut self, + params: ::launcher::parser::ParameterPacket) + -> ::launcher::parser::ResponseType; } diff --git a/src/lib.rs b/src/lib.rs index aee24af0..59461342 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,10 +47,12 @@ extern crate byteorder; extern crate bufstream; extern crate sodiumoxide; extern crate rustc_serialize; -#[macro_use] extern crate log; -#[macro_use] extern crate maidsafe_utilities; +#[macro_use] +extern crate log; +#[macro_use] +extern crate maidsafe_utilities; -#[macro_use] mod macros; +#[macro_use]mod macros; /// FFI interface. pub mod ffi; diff --git a/src/macros.rs b/src/macros.rs index 11144214..3e5308fe 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -104,7 +104,9 @@ macro_rules! group_send { // - cannot move out of captured outer variable in an `FnMut` closure // while doing a move in the closure provided to `retain()` below let mut option_dance = Some($data); - $senders.retain(|tx| tx.send(::std::convert::From::from(unwrap_option!(option_dance.take(), "Logic Error - Report a bug."))) + $senders.retain(|tx| tx.send(::std::convert::From::from( + unwrap_option!(option_dance.take(), + "Logic Error - Report a bug."))) .is_ok()); }} } @@ -226,7 +228,8 @@ macro_rules! eval_send_one { /// # #[macro_use] extern crate safe_launcher; /// fn g() -> Result<(), safe_launcher::errors::LauncherError> { /// let mut remaining_tokens = vec![]; -/// let _module = try!(parse_option!(remaining_tokens.pop(), "Invalid endpoint - Module token not found.")); +/// let _module = try!(parse_option!(remaining_tokens.pop(), +/// "Invalid endpoint - Module token not found.")); /// /// Ok(()) /// } @@ -279,7 +282,8 @@ macro_rules! parse_option { #[macro_export] macro_rules! parse_result { ($output:expr, $err_statement:expr) => { - $output.map_err(|e| $crate::errors::LauncherError::SpecificParseError(format!("{} {:?}", $err_statement.to_string(), e))) + $output.map_err(|e| $crate::errors::LauncherError::SpecificParseError( + format!("{} {:?}", $err_statement.to_string(), e))) } } @@ -291,7 +295,8 @@ macro_rules! parse_result { /// ``` /// # #[macro_use] extern crate safe_launcher; /// fn f() -> i32 { -/// let some_result: Result = Ok("Hello".to_string()); +/// let some_result: Result = +/// Ok("Hello".to_string()); /// let string_length = ffi_try!(some_result).len(); /// assert_eq!(string_length, 5); /// 0 diff --git a/src/observer.rs b/src/observer.rs index 2288b667..94408490 100644 --- a/src/observer.rs +++ b/src/observer.rs @@ -136,7 +136,7 @@ pub mod event_data { #[derive(Debug)] pub struct PendingVerification { /// Launcher nonce that was give to the Application while starting it. - pub nonce : String, + pub nonce: String, /// Action taken for this Application. pub action: Action, } @@ -145,7 +145,7 @@ pub mod event_data { #[derive(Debug)] pub struct UnverifiedSession { /// Temporary id for a session trying to pass the authentication stages. - pub id : u32, + pub id: u32, /// Action taken for this Application. pub action: Action, } @@ -154,7 +154,7 @@ pub mod event_data { #[derive(Debug)] pub struct VerifiedSession { /// Unique id of the Application managed by Launcher. - pub id : XorName, + pub id: XorName, /// Action taken for this Application. pub action: Action, } @@ -163,7 +163,7 @@ pub mod event_data { #[derive(Debug)] pub struct AppAddition { /// Result of operation. - pub result : Result, + pub result: Result, /// Local path of application binary on this machine. pub local_path: String, } @@ -172,16 +172,16 @@ pub mod event_data { #[derive(Debug)] pub struct AppAdditionData { /// Unique id of the Application managed by Launcher. - pub id : XorName, + pub id: XorName, /// Name given to the App by Launcher, - pub name: String + pub name: String, } /// Data for an app that was attempted to be removed from Launcher. #[derive(Debug)] pub struct AppRemoval { /// Unique id of the Application managed by Launcher. - pub id : XorName, + pub id: XorName, /// Result of operation. pub result: Option<::errors::LauncherError>, } @@ -190,7 +190,7 @@ pub mod event_data { #[derive(Debug)] pub struct AppModification { /// Unique id of the Application managed by Launcher. - pub id : XorName, + pub id: XorName, /// Result of operation. pub result: Result, } @@ -200,9 +200,9 @@ pub mod event_data { #[derive(Debug)] pub struct ModificationDetail { /// Name of the app. - pub name : Option, + pub name: Option, /// Absolute local path to binary. - pub local_path : Option, + pub local_path: Option, /// If this app is allowed to have access to `SAFEDrive`. pub safe_drive_access: Option, }