Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DLT file transfer packages #24

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3761380
Add definition for file transfer packages
JulianSchmid Jun 17, 2024
2870542
Correct 32bit implementation
JulianSchmid Jun 17, 2024
81dc7b6
Apply cargo fmt
JulianSchmid Jun 17, 2024
dd49f46
Add parsing code for DltFtPkg
JulianSchmid Jun 18, 2024
aa0889a
Add uint16 to file transfer unsigned int
JulianSchmid Jun 18, 2024
cb52b97
Add reconstruction buffer for dlt file transfer streams
JulianSchmid Jun 19, 2024
6d375a6
Added filetransfer buffer
JulianSchmid Jun 19, 2024
821cbd1
Resolved clippy warnings
JulianSchmid Jun 24, 2024
27ed6a2
Resolved no-std errors & add doc tags for no-std
JulianSchmid Jun 24, 2024
fff5e84
Resolved no std test errors
JulianSchmid Jun 24, 2024
3353c87
Resolved 32 bit building errors
JulianSchmid Jun 24, 2024
8ba64c8
Restricted DltFtBuffer to 64bit systems
JulianSchmid Jun 24, 2024
6fbe755
Resolved warnings on 32bit systems
JulianSchmid Jun 25, 2024
48aeaec
Resolved errors on 32bit systems
JulianSchmid Jun 25, 2024
82a46f0
Added support for 32bit systems to file transfer
JulianSchmid Jun 25, 2024
ad743e6
Resolved 32bit system compilation issue
JulianSchmid Jun 25, 2024
583fa99
Tests for dlt ft buffer new & bugfix
JulianSchmid Jun 25, 2024
49af07a
Further tests & reworks
JulianSchmid Jun 25, 2024
4cb8949
Add test for allocation failure
JulianSchmid Jun 25, 2024
a02c269
Correct 32bit test
JulianSchmid Jun 25, 2024
e03f3ea
Addition tests and fix for empty files
JulianSchmid Jun 26, 2024
ce387e4
Completed tests for dlt ft buffer
JulianSchmid Jun 28, 2024
5e74671
Add pool tests
JulianSchmid Jun 30, 2024
5efe4cc
Finalize dlt ft pool tests
JulianSchmid Jun 30, 2024
6682f16
Further tests and constants
JulianSchmid Jul 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ An complete example which includes the parsing of the ethernet & udp headers can

## References
* [Log and Trace Protocol Specification](https://www.autosar.org/fileadmin/standards/foundation/1-3/AUTOSAR_PRS_LogAndTraceProtocol.pdf)
* [COVESA DLT Filetransfer](https://github.com/COVESA/dlt-daemon/blob/603f0e4bb87478f7d3e95c89b37790e55ff1e4e5/doc/dlt_filetransfer.md)

## License
Licensed under either of Apache License, Version 2.0 or MIT license at your option. The corresponding license texts can be found in the LICENSE-APACHE file and the LICENSE-MIT file.
Expand Down
5 changes: 2 additions & 3 deletions src/control/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/// "Set Log Level" service id
pub const CMD_ID_SET_LOG_LEVEL: u32 = 0x01;
/// "Set Log Level" name
Expand Down Expand Up @@ -119,7 +118,7 @@ mod test {
use super::*;
use proptest::prelude::*;

proptest!{
proptest! {
#[test]
fn test_get_control_command_name(
unknown_id in 0x24..0xFFFu32,
Expand Down Expand Up @@ -169,4 +168,4 @@ mod test {
assert_eq!(Some("CallSWCInjection"), get_control_command_name(sw_injections_id));
}
}
}
}
2 changes: 2 additions & 0 deletions src/dlt_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ impl DltHeader {

///Deserialize a DltHeader & TpHeader from the given reader.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub fn read<T: io::Read + Sized>(reader: &mut T) -> Result<DltHeader, error::ReadError> {
use crate::error::UnsupportedDltVersionError;

Expand Down Expand Up @@ -382,6 +383,7 @@ impl DltHeader {

///Serializes the header to the given writer.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
{
let length_be = self.length.to_be_bytes();
Expand Down
2 changes: 1 addition & 1 deletion src/dlt_typed_payload.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{*, verbose::VerboseIter};
use crate::{verbose::VerboseIter, *};

/// Typed payload of a DLT log message based on the message info in the DLT
/// extended header.
Expand Down
1 change: 1 addition & 0 deletions src/error/dlt_message_length_too_small_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl core::fmt::Display for DltMessageLengthTooSmallError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for DltMessageLengthTooSmallError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
89 changes: 89 additions & 0 deletions src/error/ft_pool_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use super::*;
use crate::ft::DltFtUInt;

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum FtPoolError {
/// Error re-assembling the stream.
FtReassemble(FtReassembleError),

/// Error if a data packet for an unknown stream is received.
DataForUnknownStream { file_serial_number: DltFtUInt },

/// Error if a end packet for an unknown stream is received.
EndForUnknownStream { file_serial_number: DltFtUInt },
}

impl core::fmt::Display for FtPoolError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use FtPoolError::*;
match self {
FtReassemble(err) => err.fmt(f),
DataForUnknownStream{ file_serial_number } => write!(f, "Received a DLT file transfer 'data' packet from an unknown stream with file_serial_number {file_serial_number:?}."),
EndForUnknownStream{ file_serial_number } => write!(f, "Received a DLT file transfer 'end' packet from an unknown stream with file_serial_number {file_serial_number:?}."),

Check warning on line 22 in src/error/ft_pool_error.rs

View check run for this annotation

Codecov / codecov/patch

src/error/ft_pool_error.rs#L17-L22

Added lines #L17 - L22 were not covered by tests
}
}

Check warning on line 24 in src/error/ft_pool_error.rs

View check run for this annotation

Codecov / codecov/patch

src/error/ft_pool_error.rs#L24

Added line #L24 was not covered by tests
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for FtPoolError {}

impl From<FtReassembleError> for FtPoolError {
fn from(value: FtReassembleError) -> Self {
FtPoolError::FtReassemble(value)
}
}

#[cfg(test)]
mod tests {
/*use super::FtPoolError::*;

#[test]
fn debug() {
let err = AllocationFailure { len: 0 };
let _ = format!("{err:?}");
}

#[test]
fn clone_eq_hash_ord() {
use core::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

let err = AllocationFailure { len: 0 };
assert_eq!(err, err.clone());
let hash_a = {
let mut hasher = DefaultHasher::new();
err.hash(&mut hasher);
hasher.finish()
};
let hash_b = {
let mut hasher = DefaultHasher::new();
err.clone().hash(&mut hasher);
hasher.finish()
};
assert_eq!(hash_a, hash_b);
assert_eq!(Ordering::Equal, err.cmp(&err));
assert_eq!(Some(Ordering::Equal), err.partial_cmp(&err));
}

#[test]
fn fmt() {
let tests = [
(UnalignedTpPayloadLen { offset: 1, payload_len: 2 }, "Payload length 2 of SOMEIP TP segment (offset 1) is not a multiple of 16. This is only allowed for TP packets where the 'more segements' flag is not set."),
(SegmentTooBig { offset: 1, payload_len: 2, max: 3, }, "Overall length of TP segment (offset 1, payload len: 2) bigger then the maximum allowed size of 3."),
(ConflictingEnd { previous_end: 1, conflicting_end: 2, }, "Received a TP package (offset + len: 2) which conflicts a package that previously set the end to 1."),
(AllocationFailure { len: 0 }, "Faield to allocate 0 bytes of memory to reconstruct the SOMEIP TP packets."),
];
for test in tests {
assert_eq!(format!("{}", test.0), test.1);
}
}

#[test]
fn source() {
use std::error::Error;
assert!(AllocationFailure { len: 0 }.source().is_none());
}
*/
}
106 changes: 106 additions & 0 deletions src/error/ft_reassemble_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum FtReassembleError {
/// Error if the number of bytes of data in a "DLT file transfer" packet
/// is not matching the original in the header specified buffer size.
DataLenNotMatchingBufferSize {
header_buffer_len: u64,
data_pkt_len: u64,
data_pkt_nr: u64,
number_of_packages: u64,
},

/// Error if the number of packages & buffer len do not match the file_size.
InconsitantHeaderLenValues {
file_size: u64,
number_of_packages: u64,
buffer_size: u64,
},

/// Error if a data package with an unexpected package nr is received.
UnexpectedPackageNrInDataPkg {
expected_nr_of_packages: u64,
package_nr: u64,
},

/// File transfer is too big to be stored in memory (if the file size
/// exceeds the platform pointer width).
FileSizeTooBig {
file_size: u64,
max_allowed: u64,
},

/// Error if not enough memory could be allocated to store the file in memory.
AllocationFailure { len: usize },
}

impl core::fmt::Display for FtReassembleError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use FtReassembleError::*;
match self {
DataLenNotMatchingBufferSize{ header_buffer_len, data_pkt_len, data_pkt_nr, number_of_packages } => write!(f, "Payload length {data_pkt_len} of DLT file transfer data packet (nr {data_pkt_nr} of {number_of_packages}) is not matching the buffer len {header_buffer_len} set by the header packet."),
InconsitantHeaderLenValues{ file_size, number_of_packages, buffer_size: buffer_len } => write!(f, "DLT file transfer header packet 'file size' {file_size} is inconsistant with the 'buffer size' {buffer_len} and 'number of packages' {number_of_packages}"),
UnexpectedPackageNrInDataPkg { expected_nr_of_packages, package_nr } => write!(f, "Received a DLT file transfer data packet with the unexpected package number {package_nr} (expected number of packages based on header package is {expected_nr_of_packages})."),
FileSizeTooBig { file_size, max_allowed } => write!(f, "DLT filetransfer file size {file_size} exceeds the supported maximum of {max_allowed}."),
AllocationFailure { len } => write!(f, "Failed to allocate {len} bytes of memory to reconstruct the SOMEIP TP packets."),

Check warning on line 44 in src/error/ft_reassemble_error.rs

View check run for this annotation

Codecov / codecov/patch

src/error/ft_reassemble_error.rs#L37-L44

Added lines #L37 - L44 were not covered by tests
}
}

Check warning on line 46 in src/error/ft_reassemble_error.rs

View check run for this annotation

Codecov / codecov/patch

src/error/ft_reassemble_error.rs#L46

Added line #L46 was not covered by tests
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for FtReassembleError {}

#[cfg(test)]
mod tests {
/*use super::FtReassembleError::*;


#[test]
fn debug() {
let err = AllocationFailure { len: 0 };
let _ = format!("{err:?}");
}

#[test]
fn clone_eq_hash_ord() {
use core::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

let err = AllocationFailure { len: 0 };
assert_eq!(err, err.clone());
let hash_a = {
let mut hasher = DefaultHasher::new();
err.hash(&mut hasher);
hasher.finish()
};
let hash_b = {
let mut hasher = DefaultHasher::new();
err.clone().hash(&mut hasher);
hasher.finish()
};
assert_eq!(hash_a, hash_b);
assert_eq!(Ordering::Equal, err.cmp(&err));
assert_eq!(Some(Ordering::Equal), err.partial_cmp(&err));
}

#[test]
fn fmt() {
let tests = [
(UnalignedTpPayloadLen { offset: 1, payload_len: 2 }, "Payload length 2 of SOMEIP TP segment (offset 1) is not a multiple of 16. This is only allowed for TP packets where the 'more segements' flag is not set."),
(SegmentTooBig { offset: 1, payload_len: 2, max: 3, }, "Overall length of TP segment (offset 1, payload len: 2) bigger then the maximum allowed size of 3."),
(ConflictingEnd { previous_end: 1, conflicting_end: 2, }, "Received a TP package (offset + len: 2) which conflicts a package that previously set the end to 1."),
(AllocationFailure { len: 0 }, "Faield to allocate 0 bytes of memory to reconstruct the SOMEIP TP packets."),
];
for test in tests {
assert_eq!(format!("{}", test.0), test.1);
}
}

#[test]
fn source() {
use std::error::Error;
assert!(AllocationFailure { len: 0 }.source().is_none());
}
*/
}
7 changes: 7 additions & 0 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
mod dlt_message_length_too_small_error;
pub use dlt_message_length_too_small_error::*;

mod ft_pool_error;
pub use ft_pool_error::*;

mod ft_reassemble_error;
pub use ft_reassemble_error::*;

mod layer;
pub use layer::*;

Expand All @@ -11,6 +17,7 @@ mod range_error;
pub use range_error::*;

mod read_error;
#[cfg(feature = "std")]
pub use read_error::*;

mod storage_header_start_pattern_error;
Expand Down
1 change: 1 addition & 0 deletions src/error/packet_slice_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ impl core::fmt::Display for PacketSliceError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for PacketSliceError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use PacketSliceError::*;
Expand Down
1 change: 1 addition & 0 deletions src/error/range_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub enum RangeError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for RangeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
7 changes: 7 additions & 0 deletions src/error/read_error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#[cfg(feature = "std")]
use super::*;

///Errors that can occure on reading a dlt header.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[derive(Debug)]
pub enum ReadError {
/// Error if the slice is smaller then dlt length field or minimal size.
Expand All @@ -22,6 +24,7 @@ pub enum ReadError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for ReadError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use ReadError::*;
Expand All @@ -36,6 +39,7 @@ impl std::error::Error for ReadError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl core::fmt::Display for ReadError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use ReadError::*;
Expand All @@ -53,13 +57,15 @@ impl core::fmt::Display for ReadError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<StorageHeaderStartPatternError> for ReadError {
fn from(err: StorageHeaderStartPatternError) -> ReadError {
ReadError::StorageHeaderStartPattern(err)
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<PacketSliceError> for ReadError {
fn from(err: PacketSliceError) -> ReadError {
use PacketSliceError as I;
Expand All @@ -72,6 +78,7 @@ impl From<PacketSliceError> for ReadError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<std::io::Error> for ReadError {
fn from(err: std::io::Error) -> ReadError {
ReadError::IoError(err)
Expand Down
1 change: 1 addition & 0 deletions src/error/storage_header_start_pattern_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl core::fmt::Display for StorageHeaderStartPatternError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for StorageHeaderStartPatternError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
1 change: 1 addition & 0 deletions src/error/typed_payload_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum TypedPayloadError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for TypedPayloadError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
1 change: 1 addition & 0 deletions src/error/unexpected_end_of_slice_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl core::fmt::Display for UnexpectedEndOfSliceError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for UnexpectedEndOfSliceError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
1 change: 1 addition & 0 deletions src/error/unsupported_dlt_version_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ impl core::fmt::Display for UnsupportedDltVersionError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for UnsupportedDltVersionError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
Expand Down
1 change: 1 addition & 0 deletions src/error/verbose_decode_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl core::fmt::Display for VerboseDecodeError {
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for VerboseDecodeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use VerboseDecodeError::*;
Expand Down
Loading
Loading