Skip to content

Version 3.6.0

Latest

Choose a tag to compare

@fpagliughi fpagliughi released this 09 Jun 22:07

Timestamps & lots of fixes!

  • Added ability to get timestamp for received frames
    • New CanTimestamps type carrying socket-layer, network-stack software, and hardware receive timestamps
    • SocketOptions::set_recv_timestamp (SO_TIMESTAMPNS) and SocketOptions::set_timestamping (SO_TIMESTAMPING) to enable delivery on the socket
    • Socket::read_frame_with_timestamp, Socket::read_frame_with_timestamps, and Socket::read_frame_with_hw_timestamp on the Socket trait (default implementations return ENOSYS to preserve semver for out-of-tree Socket implementors)
    • CanSocket::has_hw_timestamps / CanFdSocket::has_hw_timestamps query interface capability via ETHTOOL_GET_TS_INFO
    • Re-exports for the SOF_TIMESTAMPING_* flag constants from the crate root
    • All read methods deliver the frame and ancillary timestamp data in a single recvmsg() call, eliminating the race window of the old SIOCGSTAMPNS approach
    • Async equivalents on the tokio::CanSocket/CanFdSocket and async_io::CanSocket/CanFdSocket wrappers
  • async_io::CanSocket and async_io::CanFdSocket gained open_if(ifindex: u32) and open_addr(&CanAddr) constructors (parity with the tokio wrappers, which previously had all three)
  • async_io::CanSocket and async_io::CanFdSocket now implement futures::Stream (yielding Result<CanFrame> / Result<CanAnyFrame>) and futures::Sink (over CanFrame / CanAnyFrame), parity with the tokio wrappers. The async-io, async-std, and smol features now pull in futures (previously it was wired in only via the tokio feature)
  • async_io::CanSocket and async_io::CanFdSocket gained try_read_frame() and try_write_frame() methods, parity with the tokio wrappers (added in #84). Both return WouldBlock when no frame is available / send buffer is full and go straight to the underlying non-blocking fd (bypassing the async-io reactor); mixing with the async-path methods is safe
  • New example tokio_recvts — tokio mirror of can_recvts, prints software and hardware timestamps alongside each frame
  • Bumped MSRV to v1.75.0
  • All frame types now derive PartialEq, Eq, and Hash — both the concrete frame structs (CanDataFrame, CanRemoteFrame, CanErrorFrame, CanFdFrame) and the wrapper enums (CanFrame, CanAnyFrame, CanRawFrame). Equality is field-wise on the underlying libc::can_frame / libc::canfd_frame, which means it includes every byte of the structure (id, dlc, flags, the libc __pad/__res0 fields, and the full data array). Note that set_data does not zero the unused trailing bytes of can_frame::data, so two semantically-equivalent frames built by different code paths may still compare unequal — callers should treat equality as "byte-identical wire image" rather than "same logical frame".
  • Enabled the extra_traits feature on the libc dependency so the trait derives can flow through (libc::can_frame / canfd_frame only derive(PartialEq, Eq, Hash) when that feature is on).
  • Bug fixes:
    • recvmsg() ancillary control buffer is now properly aligned and validated; MSG_TRUNC/MSG_CTRUNC handled correctly
    • timespec_to_duration no longer wraps on a negative tv_sec in release builds
    • From<canfd_frame> for CanFdFrame normalises non-spec lengths so dlc() and data() stay consistent and no uninitialised bytes can leak
    • TryFrom<can_frame> for CanErrorFrame forces can_dlc = CAN_MAX_DLEN so the len/dlc/data invariant holds
    • CanDataFrame::set_id and CanFdFrame::set_id preserve CAN_ERR_FLAG/CAN_RTR_FLAG bits in the ID word
    • CanId + u32 no longer panics on overflow in debug builds
    • AsPtr::as_bytes_mut now returns &mut [u8] instead of &[u8]
    • rcan CLI no longer contains duplicate loopback subcommand arms
    • examples/can_recvts.rs now requests the full set of timestamp flags so software and hardware timestamps actually arrive
    • examples/fd_send.rs now sends an actual CAN FD frame
    • fmt::UpperHex on classic frames uses raw_id() (no flag-bit leakage), zero-pads the ID to 3 chars (SFF) / 8 chars (EFF), joins data bytes without spaces, and emits #R<dlc> for remote frames so the output matches candump's log format
    • fmt::UpperHex on CanFdFrame prints the FD flags as a single hex nibble between ## and the data bytes (no stray space)
    • CanRemoteFrame::data() now returns &[] (spec-correct: remote frames carry only a DLC); use dlc() to read the requested length
    • CanInterface::create rejects names of length IFNAMSIZ and above (off-by-one — IFNAMSIZ includes the trailing NUL)
    • CAN_TERMINATION_DISABLED is now u16 (matches the rest of the termination API)
    • From<libudev::Error> preserves the underlying description on the wrapped io::Error
    • CanAddr gained hand-rolled PartialEq/Eq/Hash impls comparing (can_family, can_ifindex) only; deriving them would compare the can_addr union plus padding, which is unsound
    • CanAddr::Debug now renders the can_addr union bytes (J1939 / ISO-TP fields are no longer dropped)
    • From<sockaddr_can> for CanAddr now debug_assert!s can_family == AF_CAN
    • available_interfaces() was silently ignoring udev errors and returning an empty list of interfaces. It now returns an error on udev failure.
    • Tokio Sink::poll_close no longer attempts a spurious clear_ready(); Sink::start_send issues a single non-blocking write_frame() instead of busy-retrying via write_frame_insist
    • Typo: "socke options" → "socket options" in set_socket_option_mult doc
    • dump::Reader caps each line at 64 KiB so a malformed or hostile log can't OOM the reader; over-long lines produce InvalidCanFrame
    • dump::Reader requires exactly six mantissa digits on the timestamp (real candump format), and uses checked arithmetic so an overflow errors instead of producing a wrong timestamp
    • dump::Reader propagates remote-frame DLC parse errors via InvalidCanFrame (previously silently coerced to 0); the DLC is now parsed as a hex nibble matching candump's R<X> format
    • dump::CanDumpRecord Display now emits parseable lines for error frames (<error_bits>#<8 hex bytes>) and FD frames (##<flag-nibble><bytes>), and zero-pads the ID width (3 hex for SFF, 8 hex for EFF) on all variants
  • New Error conversions:
    • From<neli::err::NlError<T, P>> (feature netlink) — netlink errors flow into the crate-level Error via io::Error::other
    • From<dump::ParseError> (feature dump) — dump-parse errors flow into Error via io::Error::new(InvalidData, …) (passing through I/O variants)
  • Docs:
    • Socket::read_frame documents concurrent-reader semantics (each &self reader sees a disjoint subset of frames)
    • CanCtrlModes::has_mode documents that it inspects flags (kernel-reported state) and ignores pending mask bits
    • CanFdFrame::new_remote documents that CAN FD has no RTR by spec, so the method always returns None
  • Internals:
    • crate::as_bytes / crate::as_bytes_mut helpers are now unsafe fn with a proper # Safety contract; call sites annotated
  • Issues & PR's
    • #89 CanInterface binds to hardcoded nl_pid
    • #81 Remove explicit 'mio' dependency.