CFDP extracted to library #201
@ -679,7 +679,7 @@ impl<
|
|||||||
// TODO: This is the only remaining function which uses std.. the easiest way would
|
// TODO: This is the only remaining function which uses std.. the easiest way would
|
||||||
// probably be to use a static pre-allocated dest path buffer to store any concatenated
|
// probably be to use a static pre-allocated dest path buffer to store any concatenated
|
||||||
// paths.
|
// paths.
|
||||||
if dest_path.exists() && self.vfs.is_dir(dest_path.to_str().unwrap()) {
|
if dest_path.exists() && self.vfs.is_dir(dest_path.to_str().unwrap())? {
|
||||||
// Create new destination path by concatenating the last part of the source source
|
// Create new destination path by concatenating the last part of the source source
|
||||||
// name and the destination folder. For example, for a source file of /tmp/hello.txt
|
// name and the destination folder. For example, for a source file of /tmp/hello.txt
|
||||||
// and a destination name of /home/test, the resulting file name should be
|
// and a destination name of /home/test, the resulting file name should be
|
||||||
@ -696,7 +696,7 @@ impl<
|
|||||||
self.tparams.file_properties.dest_path_buf.push(source_name);
|
self.tparams.file_properties.dest_path_buf.push(source_name);
|
||||||
}
|
}
|
||||||
let dest_path_str = self.tparams.file_properties.dest_path_buf.to_str().unwrap();
|
let dest_path_str = self.tparams.file_properties.dest_path_buf.to_str().unwrap();
|
||||||
if self.vfs.exists(dest_path_str) {
|
if self.vfs.exists(dest_path_str)? {
|
||||||
self.vfs.truncate_file(dest_path_str)?;
|
self.vfs.truncate_file(dest_path_str)?;
|
||||||
} else {
|
} else {
|
||||||
self.vfs.create_file(dest_path_str)?;
|
self.vfs.create_file(dest_path_str)?;
|
||||||
|
@ -123,13 +123,15 @@ pub trait VirtualFilestore {
|
|||||||
path.file_name().and_then(|name| name.to_str())
|
path.file_name().and_then(|name| name.to_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_file(&self, path: &str) -> bool;
|
fn is_file(&self, path: &str) -> Result<bool, FilestoreError>;
|
||||||
|
|
||||||
fn is_dir(&self, path: &str) -> bool {
|
fn is_dir(&self, path: &str) -> Result<bool, FilestoreError> {
|
||||||
!self.is_file(path)
|
Ok(!self.is_file(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists(&self, path: &str) -> bool;
|
fn exists(&self, path: &str) -> Result<bool, FilestoreError>;
|
||||||
|
|
||||||
|
fn file_size(&self, path: &str) -> Result<u64, FilestoreError>;
|
||||||
|
|
||||||
/// This special function is the CFDP specific abstraction to verify the checksum of a file.
|
/// This special function is the CFDP specific abstraction to verify the checksum of a file.
|
||||||
/// This allows to keep OS specific details like reading the whole file in the most efficient
|
/// This allows to keep OS specific details like reading the whole file in the most efficient
|
||||||
@ -160,7 +162,7 @@ pub mod std_mod {
|
|||||||
|
|
||||||
impl VirtualFilestore for NativeFilestore {
|
impl VirtualFilestore for NativeFilestore {
|
||||||
fn create_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
fn create_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
||||||
if self.exists(file_path) {
|
if self.exists(file_path)? {
|
||||||
return Err(FilestoreError::FileAlreadyExists);
|
return Err(FilestoreError::FileAlreadyExists);
|
||||||
}
|
}
|
||||||
File::create(file_path)?;
|
File::create(file_path)?;
|
||||||
@ -168,10 +170,10 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn remove_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
fn remove_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
||||||
if !self.exists(file_path) {
|
if !self.exists(file_path)? {
|
||||||
return Err(FilestoreError::FileDoesNotExist);
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
}
|
}
|
||||||
if !self.is_file(file_path) {
|
if !self.is_file(file_path)? {
|
||||||
return Err(FilestoreError::IsNotFile);
|
return Err(FilestoreError::IsNotFile);
|
||||||
}
|
}
|
||||||
fs::remove_file(file_path)?;
|
fs::remove_file(file_path)?;
|
||||||
@ -179,10 +181,10 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn truncate_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
fn truncate_file(&self, file_path: &str) -> Result<(), FilestoreError> {
|
||||||
if !self.exists(file_path) {
|
if !self.exists(file_path)? {
|
||||||
return Err(FilestoreError::FileDoesNotExist);
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
}
|
}
|
||||||
if !self.is_file(file_path) {
|
if !self.is_file(file_path)? {
|
||||||
return Err(FilestoreError::IsNotFile);
|
return Err(FilestoreError::IsNotFile);
|
||||||
}
|
}
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
@ -201,10 +203,10 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn remove_dir(&self, dir_path: &str, all: bool) -> Result<(), FilestoreError> {
|
fn remove_dir(&self, dir_path: &str, all: bool) -> Result<(), FilestoreError> {
|
||||||
if !self.exists(dir_path) {
|
if !self.exists(dir_path)? {
|
||||||
return Err(FilestoreError::DirDoesNotExist);
|
return Err(FilestoreError::DirDoesNotExist);
|
||||||
}
|
}
|
||||||
if !self.is_dir(dir_path) {
|
if !self.is_dir(dir_path)? {
|
||||||
return Err(FilestoreError::IsNotDirectory);
|
return Err(FilestoreError::IsNotDirectory);
|
||||||
}
|
}
|
||||||
if !all {
|
if !all {
|
||||||
@ -229,10 +231,10 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
if !self.exists(file_name) {
|
if !self.exists(file_name)? {
|
||||||
return Err(FilestoreError::FileDoesNotExist);
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
}
|
}
|
||||||
if !self.is_file(file_name) {
|
if !self.is_file(file_name)? {
|
||||||
return Err(FilestoreError::IsNotFile);
|
return Err(FilestoreError::IsNotFile);
|
||||||
}
|
}
|
||||||
let mut file = File::open(file_name)?;
|
let mut file = File::open(file_name)?;
|
||||||
@ -242,10 +244,10 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_data(&self, file: &str, offset: u64, buf: &[u8]) -> Result<(), FilestoreError> {
|
fn write_data(&self, file: &str, offset: u64, buf: &[u8]) -> Result<(), FilestoreError> {
|
||||||
if !self.exists(file) {
|
if !self.exists(file)? {
|
||||||
return Err(FilestoreError::FileDoesNotExist);
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
}
|
}
|
||||||
if !self.is_file(file) {
|
if !self.is_file(file)? {
|
||||||
return Err(FilestoreError::IsNotFile);
|
return Err(FilestoreError::IsNotFile);
|
||||||
}
|
}
|
||||||
let mut file = OpenOptions::new().write(true).open(file)?;
|
let mut file = OpenOptions::new().write(true).open(file)?;
|
||||||
@ -254,17 +256,28 @@ pub mod std_mod {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_file(&self, path: &str) -> bool {
|
fn is_file(&self, str_path: &str) -> Result<bool, FilestoreError> {
|
||||||
let path = Path::new(path);
|
let path = Path::new(str_path);
|
||||||
path.is_file()
|
if !self.exists(str_path)? {
|
||||||
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
|
}
|
||||||
|
Ok(path.is_file())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists(&self, path: &str) -> bool {
|
fn exists(&self, path: &str) -> Result<bool, FilestoreError> {
|
||||||
let path = Path::new(path);
|
let path = Path::new(path);
|
||||||
if !path.exists() {
|
Ok(self.exists_internal(path))
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
fn file_size(&self, str_path: &str) -> Result<u64, FilestoreError> {
|
||||||
|
let path = Path::new(str_path);
|
||||||
|
if !self.exists_internal(path) {
|
||||||
|
return Err(FilestoreError::FileDoesNotExist);
|
||||||
}
|
}
|
||||||
true
|
if !path.is_file() {
|
||||||
|
return Err(FilestoreError::IsNotFile);
|
||||||
|
}
|
||||||
|
Ok(path.metadata()?.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checksum_verify(
|
fn checksum_verify(
|
||||||
@ -324,6 +337,13 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
Ok(checksum)
|
Ok(checksum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exists_internal(&self, path: &Path) -> bool {
|
||||||
|
if !path.exists() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,32 +370,34 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let path = Path::new(&file_path);
|
let path = Path::new(&file_path);
|
||||||
assert!(path.exists());
|
assert!(path.exists());
|
||||||
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_native_fs_file_exists() {
|
fn test_basic_native_fs_file_exists() {
|
||||||
let tmpdir = tempdir().expect("creating tmpdir failed");
|
let tmpdir = tempdir().expect("creating tmpdir failed");
|
||||||
let file_path = tmpdir.path().join("test.txt");
|
let file_path = tmpdir.path().join("test.txt");
|
||||||
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_file(file_path.to_str().expect("getting str for file failed"))
|
.create_file(file_path.to_str().expect("getting str for file failed"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_native_fs_dir_exists() {
|
fn test_basic_native_fs_dir_exists() {
|
||||||
let tmpdir = tempdir().expect("creating tmpdir failed");
|
let tmpdir = tempdir().expect("creating tmpdir failed");
|
||||||
let dir_path = tmpdir.path().join("testdir");
|
let dir_path = tmpdir.path().join("testdir");
|
||||||
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_dir(dir_path.to_str().expect("getting str for file failed"))
|
.create_dir(dir_path.to_str().expect("getting str for file failed"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
assert!(NATIVE_FS.is_dir(dir_path.as_path().to_str().unwrap()));
|
assert!(NATIVE_FS
|
||||||
|
.is_dir(dir_path.as_path().to_str().unwrap())
|
||||||
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -385,23 +407,23 @@ mod tests {
|
|||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_file(file_path.to_str().expect("getting str for file failed"))
|
.create_file(file_path.to_str().expect("getting str for file failed"))
|
||||||
.expect("creating file failed");
|
.expect("creating file failed");
|
||||||
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.remove_file(file_path.to_str().unwrap())
|
.remove_file(file_path.to_str().unwrap())
|
||||||
.expect("removing file failed");
|
.expect("removing file failed");
|
||||||
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_native_fs_write() {
|
fn test_basic_native_fs_write() {
|
||||||
let tmpdir = tempdir().expect("creating tmpdir failed");
|
let tmpdir = tempdir().expect("creating tmpdir failed");
|
||||||
let file_path = tmpdir.path().join("test.txt");
|
let file_path = tmpdir.path().join("test.txt");
|
||||||
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_file(file_path.to_str().expect("getting str for file failed"))
|
.create_file(file_path.to_str().expect("getting str for file failed"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
|
||||||
println!("{}", file_path.to_str().unwrap());
|
println!("{}", file_path.to_str().unwrap());
|
||||||
let write_data = "hello world\n";
|
let write_data = "hello world\n";
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
@ -415,12 +437,12 @@ mod tests {
|
|||||||
fn test_basic_native_fs_read() {
|
fn test_basic_native_fs_read() {
|
||||||
let tmpdir = tempdir().expect("creating tmpdir failed");
|
let tmpdir = tempdir().expect("creating tmpdir failed");
|
||||||
let file_path = tmpdir.path().join("test.txt");
|
let file_path = tmpdir.path().join("test.txt");
|
||||||
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_file(file_path.to_str().expect("getting str for file failed"))
|
.create_file(file_path.to_str().expect("getting str for file failed"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(file_path.to_str().unwrap()).unwrap());
|
||||||
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()));
|
assert!(NATIVE_FS.is_file(file_path.to_str().unwrap()).unwrap());
|
||||||
println!("{}", file_path.to_str().unwrap());
|
println!("{}", file_path.to_str().unwrap());
|
||||||
let write_data = "hello world\n";
|
let write_data = "hello world\n";
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
@ -449,15 +471,15 @@ mod tests {
|
|||||||
fn test_remove_dir() {
|
fn test_remove_dir() {
|
||||||
let tmpdir = tempdir().expect("creating tmpdir failed");
|
let tmpdir = tempdir().expect("creating tmpdir failed");
|
||||||
let dir_path = tmpdir.path().join("testdir");
|
let dir_path = tmpdir.path().join("testdir");
|
||||||
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.create_dir(dir_path.to_str().expect("getting str for file failed"))
|
.create_dir(dir_path.to_str().expect("getting str for file failed"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
NATIVE_FS
|
NATIVE_FS
|
||||||
.remove_dir(dir_path.to_str().unwrap(), false)
|
.remove_dir(dir_path.to_str().unwrap(), false)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -544,7 +566,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let result = NATIVE_FS.remove_dir(dir_path.to_str().unwrap(), true);
|
let result = NATIVE_FS.remove_dir(dir_path.to_str().unwrap(), true);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()));
|
assert!(!NATIVE_FS.exists(dir_path.to_str().unwrap()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -540,6 +540,14 @@ pub mod alloc_mod {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_source_file(&self) -> bool {
|
||||||
|
self.static_fields.source_file_len > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_dest_file(&self) -> bool {
|
||||||
|
self.static_fields.dest_file_len > 0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn source_file(&self) -> Result<&str, Utf8Error> {
|
pub fn source_file(&self) -> Result<&str, Utf8Error> {
|
||||||
core::str::from_utf8(
|
core::str::from_utf8(
|
||||||
&self.static_fields.source_file_buf[0..self.static_fields.source_file_len],
|
&self.static_fields.source_file_buf[0..self.static_fields.source_file_len],
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
|
use core::str::Utf8Error;
|
||||||
|
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
cfdp::{pdu::FileDirectiveType, PduType},
|
cfdp::{
|
||||||
util::UnsignedByteField,
|
lv::Lv,
|
||||||
|
pdu::{
|
||||||
|
metadata::{MetadataGenericParams, MetadataPduCreator},
|
||||||
|
CommonPduConfig, FileDirectiveType, PduHeader,
|
||||||
|
},
|
||||||
|
Direction, LargeFileFlag, PduType,
|
||||||
|
},
|
||||||
|
util::{UnsignedByteField, UnsignedEnum},
|
||||||
ByteConversionError,
|
ByteConversionError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::seq_count::SequenceCountProvider;
|
use crate::seq_count::SequenceCountProvider;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
filestore::VirtualFilestore,
|
filestore::{FilestoreError, VirtualFilestore},
|
||||||
request::{ReadablePutRequest, StaticPutRequestCacher},
|
request::{ReadablePutRequest, StaticPutRequestCacher},
|
||||||
user::CfdpUser,
|
user::CfdpUser,
|
||||||
LocalEntityConfig, PacketInfo, PacketTarget, PduSendProvider, RemoteEntityConfig,
|
LocalEntityConfig, PacketInfo, PacketTarget, PduSendProvider, RemoteEntityConfig,
|
||||||
@ -30,12 +39,13 @@ pub enum TransactionStep {
|
|||||||
NoticeOfCompletion = 10,
|
NoticeOfCompletion = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct FileParams {
|
pub struct FileParams {
|
||||||
pub progress: usize,
|
pub progress: usize,
|
||||||
pub segment_len: usize,
|
pub segment_len: usize,
|
||||||
pub crc32: Option<[u8; 4]>,
|
//pub crc32: Option<[u8; 4]>,
|
||||||
pub metadata_only: bool,
|
pub metadata_only: bool,
|
||||||
pub file_size: usize,
|
pub file_size: u64,
|
||||||
pub no_eof: bool,
|
pub no_eof: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +86,12 @@ pub enum SourceError {
|
|||||||
PutRequestAlreadyActive,
|
PutRequestAlreadyActive,
|
||||||
#[error("error caching put request")]
|
#[error("error caching put request")]
|
||||||
PutRequestCaching(ByteConversionError),
|
PutRequestCaching(ByteConversionError),
|
||||||
|
#[error("filestore error: {0}")]
|
||||||
|
FilestoreError(#[from] FilestoreError),
|
||||||
|
#[error("source file does not have valid UTF8 format: {0}")]
|
||||||
|
SourceFileNotValidUtf8(Utf8Error),
|
||||||
|
#[error("destination file does not have valid UTF8 format: {0}")]
|
||||||
|
DestFileNotValidUtf8(Utf8Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
@ -99,7 +115,12 @@ pub struct SourceHandler<
|
|||||||
remote_cfg_table: RemoteCfgTable,
|
remote_cfg_table: RemoteCfgTable,
|
||||||
vfs: Vfs,
|
vfs: Vfs,
|
||||||
state_helper: StateHelper,
|
state_helper: StateHelper,
|
||||||
|
// Transfer related state information
|
||||||
tstate: Option<TransferState>,
|
tstate: Option<TransferState>,
|
||||||
|
// File specific transfer fields
|
||||||
|
fparams: FileParams,
|
||||||
|
// PDU configuration is cached so it can be re-used for all PDUs generated for file transfers.
|
||||||
|
pdu_conf: CommonPduConfig,
|
||||||
seq_count_provider: SeqCountProvider,
|
seq_count_provider: SeqCountProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +148,8 @@ impl<
|
|||||||
put_request_cacher,
|
put_request_cacher,
|
||||||
state_helper: Default::default(),
|
state_helper: Default::default(),
|
||||||
tstate: Default::default(),
|
tstate: Default::default(),
|
||||||
|
fparams: Default::default(),
|
||||||
|
pdu_conf: Default::default(),
|
||||||
seq_count_provider,
|
seq_count_provider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,10 +226,6 @@ impl<
|
|||||||
}
|
}
|
||||||
self.put_request_cacher.set(put_request)?;
|
self.put_request_cacher.set(put_request)?;
|
||||||
self.state_helper.state = super::State::Busy;
|
self.state_helper.state = super::State::Busy;
|
||||||
let source_file = self.put_request_cacher.source_file().unwrap();
|
|
||||||
if !self.vfs.exists(source_file) {
|
|
||||||
// TODO: Specific error.
|
|
||||||
}
|
|
||||||
let remote_cfg = self.remote_cfg_table.get(
|
let remote_cfg = self.remote_cfg_table.get(
|
||||||
self.put_request_cacher
|
self.put_request_cacher
|
||||||
.static_fields
|
.static_fields
|
||||||
@ -218,7 +237,6 @@ impl<
|
|||||||
}
|
}
|
||||||
let remote_cfg = remote_cfg.unwrap();
|
let remote_cfg = remote_cfg.unwrap();
|
||||||
self.state_helper.num_packets_ready = 0;
|
self.state_helper.num_packets_ready = 0;
|
||||||
//self.tstate.remote_cfg = Some(*remote_cfg);
|
|
||||||
let transmission_mode = if self.put_request_cacher.static_fields.trans_mode.is_some() {
|
let transmission_mode = if self.put_request_cacher.static_fields.trans_mode.is_some() {
|
||||||
self.put_request_cacher.static_fields.trans_mode.unwrap()
|
self.put_request_cacher.static_fields.trans_mode.unwrap()
|
||||||
} else {
|
} else {
|
||||||
@ -252,12 +270,130 @@ impl<
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transmission_mode(&self) {}
|
pub fn transmission_mode(&self) -> Option<super::TransmissionMode> {
|
||||||
|
self.tstate.map(|v| v.transmission_mode)
|
||||||
|
}
|
||||||
|
|
||||||
fn fsm_busy(&mut self, cfdp_user: &mut impl CfdpUser) -> Result<u32, SourceError> {
|
fn fsm_busy(&mut self, cfdp_user: &mut impl CfdpUser) -> Result<u32, SourceError> {
|
||||||
|
if self.state_helper.step == TransactionStep::Idle {
|
||||||
|
self.state_helper.step = TransactionStep::TransactionStart;
|
||||||
|
}
|
||||||
|
if self.state_helper.step == TransactionStep::TransactionStart {
|
||||||
|
self.handle_transaction_start(cfdp_user)?;
|
||||||
|
self.state_helper.step = TransactionStep::SendingMetadata;
|
||||||
|
}
|
||||||
|
if self.state_helper.step == TransactionStep::SendingMetadata {
|
||||||
|
self.prepare_and_send_metadata_pdu();
|
||||||
|
}
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_transaction_start(
|
||||||
|
&mut self,
|
||||||
|
cfdp_user: &mut impl CfdpUser,
|
||||||
|
) -> Result<(), SourceError> {
|
||||||
|
let tstate = &self.tstate.expect("transfer state unexpectedly empty");
|
||||||
|
if !self.put_request_cacher.has_source_file() {
|
||||||
|
self.fparams.metadata_only = true;
|
||||||
|
self.fparams.no_eof = true;
|
||||||
|
} else {
|
||||||
|
let source_file = self
|
||||||
|
.put_request_cacher
|
||||||
|
.source_file()
|
||||||
|
.map_err(SourceError::SourceFileNotValidUtf8)?;
|
||||||
|
if !self.vfs.exists(source_file)? {
|
||||||
|
return Err(SourceError::FilestoreError(
|
||||||
|
FilestoreError::FileDoesNotExist,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// We expect the destination file path to consist of valid UTF-8 characters as well.
|
||||||
|
self.put_request_cacher
|
||||||
|
.dest_file()
|
||||||
|
.map_err(SourceError::DestFileNotValidUtf8)?;
|
||||||
|
if self.vfs.file_size(source_file)? > u32::MAX as u64 {
|
||||||
|
self.pdu_conf.file_flag = LargeFileFlag::Large
|
||||||
|
} else {
|
||||||
|
self.pdu_conf.file_flag = LargeFileFlag::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Both the source entity and destination entity ID field must have the same size.
|
||||||
|
// We use the larger of either the Put Request destination ID or the local entity ID
|
||||||
|
// as the size for the new entity IDs.
|
||||||
|
let larger_entity_width = core::cmp::max(
|
||||||
|
self.local_cfg.id.size(),
|
||||||
|
self.put_request_cacher.static_fields.destination_id.size(),
|
||||||
|
);
|
||||||
|
let create_id = |cached_id: &UnsignedByteField| {
|
||||||
|
if larger_entity_width != cached_id.size() {
|
||||||
|
UnsignedByteField::new(larger_entity_width, cached_id.value_const())
|
||||||
|
} else {
|
||||||
|
self.local_cfg.id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.pdu_conf
|
||||||
|
.set_source_and_dest_id(
|
||||||
|
create_id(&self.local_cfg.id),
|
||||||
|
create_id(&self.put_request_cacher.static_fields.destination_id),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
// Set up other PDU configuration fields.
|
||||||
|
self.pdu_conf.direction = Direction::TowardsReceiver;
|
||||||
|
self.pdu_conf.crc_flag = tstate.remote_cfg.crc_on_transmission_by_default.into();
|
||||||
|
self.pdu_conf.transaction_seq_num = *tstate.transaction_id.seq_num();
|
||||||
|
self.pdu_conf.trans_mode = tstate.transmission_mode;
|
||||||
|
|
||||||
|
cfdp_user.transaction_indication(&tstate.transaction_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_and_send_metadata_pdu(&self) {
|
||||||
|
let tstate = &self.tstate.expect("transfer state unexpectedly empty");
|
||||||
|
if self.fparams.metadata_only {
|
||||||
|
let metadata_params = MetadataGenericParams::new(
|
||||||
|
tstate.closure_requested,
|
||||||
|
tstate.remote_cfg.default_crc_type,
|
||||||
|
self.fparams.file_size,
|
||||||
|
);
|
||||||
|
let metadata_pdu = MetadataPduCreator::new(
|
||||||
|
PduHeader::new_no_file_data(self.pdu_conf, 0),
|
||||||
|
metadata_params,
|
||||||
|
Lv::new_empty(),
|
||||||
|
Lv::new_empty(),
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
//self.pdu_sender.send_pdu(pdu_type, file_directive_type, raw_pdu)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
assert self._put_req is not None
|
||||||
|
options = []
|
||||||
|
if self._put_req.metadata_only:
|
||||||
|
params = MetadataParams(
|
||||||
|
closure_requested=self._params.closure_requested,
|
||||||
|
checksum_type=self._crc_helper.checksum_type,
|
||||||
|
file_size=0,
|
||||||
|
dest_file_name=None,
|
||||||
|
source_file_name=None,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Funny name.
|
||||||
|
params = self._prepare_metadata_base_params_with_metadata()
|
||||||
|
if self._put_req.fs_requests is not None:
|
||||||
|
for fs_request in self._put_req.fs_requests:
|
||||||
|
options.append(fs_request)
|
||||||
|
if self._put_req.fault_handler_overrides is not None:
|
||||||
|
for fh_override in self._put_req.fault_handler_overrides:
|
||||||
|
options.append(fh_override)
|
||||||
|
if self._put_req.flow_label_tlv is not None:
|
||||||
|
options.append(self._put_req.flow_label_tlv)
|
||||||
|
if self._put_req.msgs_to_user is not None:
|
||||||
|
for msg_to_user in self._put_req.msgs_to_user:
|
||||||
|
options.append(msg_to_user)
|
||||||
|
self._add_packet_to_be_sent(
|
||||||
|
MetadataPdu(pdu_conf=self._params.pdu_conf, params=params, options=options)
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_finished_pdu(&mut self) {}
|
fn handle_finished_pdu(&mut self) {}
|
||||||
|
|
||||||
fn handle_nak_pdu(&mut self) {}
|
fn handle_nak_pdu(&mut self) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user