use crate::{
as_bytes, as_bytes_mut,
frame::{can_frame_default, canfd_frame_default, AsPtr},
id::CAN_ERR_MASK,
CanAnyFrame, CanFdFrame, CanFrame, CanRawFrame, Error, IoError, IoErrorKind, IoResult, Result,
};
pub use embedded_can::{
self, blocking::Can as BlockingCan, nb::Can as NonBlockingCan, ExtendedId,
Frame as EmbeddedFrame, Id, StandardId,
};
use libc::{canid_t, socklen_t, AF_CAN, EINPROGRESS};
use socket2::SockAddr;
use std::{
fmt,
io::{Read, Write},
mem::{size_of, size_of_val},
os::{
raw::{c_int, c_void},
unix::io::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd},
},
ptr,
time::Duration,
};
pub use libc::{
CANFD_MTU, CAN_MTU, CAN_RAW, CAN_RAW_ERR_FILTER, CAN_RAW_FD_FRAMES, CAN_RAW_FILTER,
CAN_RAW_JOIN_FILTERS, CAN_RAW_LOOPBACK, CAN_RAW_RECV_OWN_MSGS, SOL_CAN_BASE, SOL_CAN_RAW,
};
pub use crate::CanAddr;
pub trait ShouldRetry {
fn should_retry(&self) -> bool;
}
impl ShouldRetry for IoError {
fn should_retry(&self) -> bool {
match self.kind() {
IoErrorKind::WouldBlock => true,
IoErrorKind::Other => {
matches!(self.raw_os_error(), Some(errno) if errno == EINPROGRESS)
}
_ => false,
}
}
}
impl<E: fmt::Debug> ShouldRetry for IoResult<E> {
fn should_retry(&self) -> bool {
match *self {
Err(ref e) => e.should_retry(),
_ => false,
}
}
}
fn raw_open_socket(addr: &CanAddr) -> IoResult<socket2::Socket> {
let af_can = socket2::Domain::from(AF_CAN);
let can_raw = socket2::Protocol::from(CAN_RAW);
let sock = socket2::Socket::new_raw(af_can, socket2::Type::RAW, Some(can_raw))?;
sock.bind(&SockAddr::from(*addr))?;
Ok(sock)
}
#[deprecated(since = "3.4.0", note = "Moved into `SocketOptions` trait")]
#[inline]
pub fn set_socket_option<T>(fd: c_int, level: c_int, name: c_int, val: &T) -> IoResult<()> {
let ret = unsafe {
libc::setsockopt(
fd,
level,
name,
val as *const _ as *const c_void,
size_of::<T>() as socklen_t,
)
};
match ret {
0 => Ok(()),
_ => Err(IoError::last_os_error()),
}
}
#[deprecated(since = "3.4.0", note = "Moved into `SocketOptions` trait")]
pub fn set_socket_option_mult<T>(
fd: c_int,
level: c_int,
name: c_int,
values: &[T],
) -> IoResult<()> {
let ret = if values.is_empty() {
unsafe { libc::setsockopt(fd, level, name, ptr::null(), 0) }
} else {
unsafe {
libc::setsockopt(
fd,
level,
name,
values.as_ptr().cast(),
size_of_val(values) as socklen_t,
)
}
};
match ret {
0 => Ok(()),
_ => Err(IoError::last_os_error()),
}
}
pub trait Socket: AsRawFd {
fn open(ifname: &str) -> IoResult<Self>
where
Self: Sized,
{
let addr = CanAddr::from_iface(ifname)?;
Self::open_addr(&addr)
}
fn open_iface(ifindex: u32) -> IoResult<Self>
where
Self: Sized,
{
let addr = CanAddr::new(ifindex);
Self::open_addr(&addr)
}
fn open_addr(addr: &CanAddr) -> IoResult<Self>
where
Self: Sized;
fn as_raw_socket(&self) -> &socket2::Socket;
fn as_raw_socket_mut(&mut self) -> &mut socket2::Socket;
fn nonblocking(&self) -> IoResult<bool> {
self.as_raw_socket().nonblocking()
}
fn set_nonblocking(&self, nonblocking: bool) -> IoResult<()> {
self.as_raw_socket().set_nonblocking(nonblocking)
}
type FrameType;
fn read_timeout(&self) -> IoResult<Option<Duration>> {
self.as_raw_socket().read_timeout()
}
fn set_read_timeout<D>(&self, duration: D) -> IoResult<()>
where
D: Into<Option<Duration>>,
{
self.as_raw_socket().set_read_timeout(duration.into())
}
fn write_timeout(&self) -> IoResult<Option<Duration>> {
self.as_raw_socket().write_timeout()
}
fn set_write_timeout<D>(&self, duration: D) -> IoResult<()>
where
D: Into<Option<Duration>>,
{
self.as_raw_socket().set_write_timeout(duration.into())
}
fn read_frame(&self) -> IoResult<Self::FrameType>;
fn read_frame_timeout(&self, timeout: Duration) -> IoResult<Self::FrameType> {
use nix::poll::{poll, PollFd, PollFlags, PollTimeout};
let pollfd = PollFd::new(
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) },
PollFlags::POLLIN,
);
match poll(
&mut [pollfd],
timeout.try_into().unwrap_or(PollTimeout::MAX),
)? {
0 => Err(IoErrorKind::TimedOut.into()),
_ => self.read_frame(),
}
}
fn write_frame<F>(&self, frame: &F) -> IoResult<()>
where
F: Into<Self::FrameType> + AsPtr;
fn write_frame_insist<F>(&self, frame: &F) -> IoResult<()>
where
F: Into<Self::FrameType> + AsPtr,
{
loop {
match self.write_frame(frame) {
Ok(v) => return Ok(v),
Err(e) if e.should_retry() => (),
Err(e) => return Err(e),
}
}
}
}
pub trait SocketOptions: AsRawFd {
fn set_socket_option<T>(&self, level: c_int, name: c_int, val: &T) -> IoResult<()> {
let ret = unsafe {
libc::setsockopt(
self.as_raw_fd(),
level,
name,
val as *const _ as *const c_void,
size_of::<T>() as socklen_t,
)
};
match ret {
0 => Ok(()),
_ => Err(IoError::last_os_error()),
}
}
fn set_socket_option_mult<T>(&self, level: c_int, name: c_int, values: &[T]) -> IoResult<()> {
let ret = if values.is_empty() {
unsafe { libc::setsockopt(self.as_raw_fd(), level, name, ptr::null(), 0) }
} else {
unsafe {
libc::setsockopt(
self.as_raw_fd(),
level,
name,
values.as_ptr().cast(),
size_of_val(values) as socklen_t,
)
}
};
match ret {
0 => Ok(()),
_ => Err(IoError::last_os_error()),
}
}
fn set_filters<F>(&self, filters: &[F]) -> IoResult<()>
where
F: Into<CanFilter> + Copy,
{
let filters: Vec<CanFilter> = filters.iter().map(|f| (*f).into()).collect();
self.set_socket_option_mult(SOL_CAN_RAW, CAN_RAW_FILTER, &filters)
}
fn set_filter_drop_all(&self) -> IoResult<()> {
let filters: &[CanFilter] = &[];
self.set_socket_option_mult(SOL_CAN_RAW, CAN_RAW_FILTER, filters)
}
fn set_filter_accept_all(&self) -> IoResult<()> {
self.set_filters(&[(0, 0)])
}
fn set_error_filter(&self, mask: u32) -> IoResult<()> {
self.set_socket_option(SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
}
#[inline(always)]
fn set_error_filter_drop_all(&self) -> IoResult<()> {
self.set_error_filter(0)
}
#[inline(always)]
fn set_error_filter_accept_all(&self) -> IoResult<()> {
self.set_error_filter(CAN_ERR_MASK)
}
fn set_error_mask(&self, mask: u32) -> IoResult<()> {
self.set_socket_option(SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
}
fn set_loopback(&self, enabled: bool) -> IoResult<()> {
let loopback = c_int::from(enabled);
self.set_socket_option(SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
}
fn set_recv_own_msgs(&self, enabled: bool) -> IoResult<()> {
let recv_own_msgs = c_int::from(enabled);
self.set_socket_option(SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs)
}
fn set_join_filters(&self, enabled: bool) -> IoResult<()> {
let join_filters = c_int::from(enabled);
self.set_socket_option(SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &join_filters)
}
}
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct CanSocket(socket2::Socket);
impl CanSocket {
pub fn read_raw_frame(&self) -> IoResult<libc::can_frame> {
let mut frame = can_frame_default();
self.as_raw_socket().read_exact(as_bytes_mut(&mut frame))?;
Ok(frame)
}
}
impl Socket for CanSocket {
type FrameType = CanFrame;
fn open_addr(addr: &CanAddr) -> IoResult<Self> {
let sock = raw_open_socket(addr)?;
Ok(Self(sock))
}
fn as_raw_socket(&self) -> &socket2::Socket {
&self.0
}
fn as_raw_socket_mut(&mut self) -> &mut socket2::Socket {
&mut self.0
}
fn write_frame<F>(&self, frame: &F) -> IoResult<()>
where
F: Into<CanFrame> + AsPtr,
{
self.as_raw_socket().write_all(frame.as_bytes())
}
fn read_frame(&self) -> IoResult<CanFrame> {
let frame = self.read_raw_frame()?;
Ok(frame.into())
}
}
impl embedded_can::blocking::Can for CanSocket {
type Frame = CanFrame;
type Error = Error;
fn receive(&mut self) -> Result<Self::Frame> {
match self.read_frame() {
Ok(CanFrame::Error(frame)) => Err(frame.into_error().into()),
Ok(frame) => Ok(frame),
Err(e) => Err(e.into()),
}
}
fn transmit(&mut self, frame: &Self::Frame) -> Result<()> {
self.write_frame_insist(frame)?;
Ok(())
}
}
impl SocketOptions for CanSocket {}
impl embedded_can::nb::Can for CanSocket {
type Frame = CanFrame;
type Error = Error;
fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
match self.read_frame() {
Ok(CanFrame::Error(frame)) => Err(Error::from(frame.into_error()).into()),
Ok(frame) => Ok(frame),
Err(err) if err.should_retry() => Err(nb::Error::WouldBlock),
Err(err) => Err(Error::from(err).into()),
}
}
fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
match self.write_frame(frame) {
Ok(_) => Ok(None),
Err(err) if err.should_retry() => Err(nb::Error::WouldBlock),
Err(err) => Err(Error::from(err).into()),
}
}
}
impl AsRawFd for CanSocket {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl From<OwnedFd> for CanSocket {
fn from(fd: OwnedFd) -> Self {
Self(socket2::Socket::from(fd))
}
}
impl IntoRawFd for CanSocket {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
impl AsFd for CanSocket {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl Read for CanSocket {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
self.0.read(buf)
}
}
impl Write for CanSocket {
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> IoResult<()> {
self.0.flush()
}
}
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct CanFdSocket(socket2::Socket);
impl CanFdSocket {
fn set_fd_mode(sock: socket2::Socket, enable: bool) -> IoResult<socket2::Socket> {
let enable = enable as c_int;
let ret = unsafe {
libc::setsockopt(
sock.as_raw_fd(),
SOL_CAN_RAW,
CAN_RAW_FD_FRAMES,
&enable as *const _ as *const c_void,
size_of::<c_int>() as u32,
)
};
match ret {
0 => Ok(sock),
_ => Err(IoError::last_os_error()),
}
}
pub fn read_raw_frame(&self) -> IoResult<CanRawFrame> {
let mut fdframe = canfd_frame_default();
match self.as_raw_socket().read(as_bytes_mut(&mut fdframe))? {
CAN_MTU => {
let mut frame = can_frame_default();
as_bytes_mut(&mut frame)[..CAN_MTU].copy_from_slice(&as_bytes(&fdframe)[..CAN_MTU]);
Ok(frame.into())
}
CANFD_MTU => Ok(fdframe.into()),
_ => Err(IoError::last_os_error()),
}
}
}
impl Socket for CanFdSocket {
type FrameType = CanAnyFrame;
fn open_addr(addr: &CanAddr) -> IoResult<Self> {
raw_open_socket(addr)
.and_then(|sock| Self::set_fd_mode(sock, true))
.map(Self)
}
fn as_raw_socket(&self) -> &socket2::Socket {
&self.0
}
fn as_raw_socket_mut(&mut self) -> &mut socket2::Socket {
&mut self.0
}
fn write_frame<F>(&self, frame: &F) -> IoResult<()>
where
F: Into<Self::FrameType> + AsPtr,
{
self.as_raw_socket().write_all(frame.as_bytes())
}
fn read_frame(&self) -> IoResult<CanAnyFrame> {
let mut fdframe = canfd_frame_default();
match self.as_raw_socket().read(as_bytes_mut(&mut fdframe))? {
CAN_MTU => {
let mut frame = can_frame_default();
as_bytes_mut(&mut frame)[..CAN_MTU].copy_from_slice(&as_bytes(&fdframe)[..CAN_MTU]);
Ok(CanFrame::from(frame).into())
}
CANFD_MTU => Ok(CanFdFrame::from(fdframe).into()),
_ => Err(IoError::last_os_error()),
}
}
}
impl SocketOptions for CanFdSocket {}
impl embedded_can::blocking::Can for CanFdSocket {
type Frame = CanAnyFrame;
type Error = Error;
fn receive(&mut self) -> Result<Self::Frame> {
match self.read_frame() {
Ok(CanAnyFrame::Error(frame)) => Err(frame.into_error().into()),
Ok(frame) => Ok(frame),
Err(e) => Err(e.into()),
}
}
fn transmit(&mut self, frame: &Self::Frame) -> Result<()> {
self.write_frame_insist(frame)?;
Ok(())
}
}
impl embedded_can::nb::Can for CanFdSocket {
type Frame = CanAnyFrame;
type Error = Error;
fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
match self.read_frame() {
Ok(CanAnyFrame::Error(frame)) => Err(Error::from(frame.into_error()).into()),
Ok(frame) => Ok(frame),
Err(err) if err.should_retry() => Err(nb::Error::WouldBlock),
Err(err) => Err(Error::from(err).into()),
}
}
fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
match self.write_frame(frame) {
Ok(_) => Ok(None),
Err(err) if err.should_retry() => Err(nb::Error::WouldBlock),
Err(err) => Err(Error::from(err).into()),
}
}
}
impl AsRawFd for CanFdSocket {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl From<OwnedFd> for CanFdSocket {
fn from(fd: OwnedFd) -> CanFdSocket {
Self(socket2::Socket::from(fd))
}
}
impl TryFrom<CanSocket> for CanFdSocket {
type Error = IoError;
fn try_from(sock: CanSocket) -> std::result::Result<Self, Self::Error> {
let CanSocket(sock2) = sock;
let sock = CanFdSocket::set_fd_mode(sock2, true)?;
Ok(CanFdSocket(sock))
}
}
impl IntoRawFd for CanFdSocket {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
impl AsFd for CanFdSocket {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl Read for CanFdSocket {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
self.0.read(buf)
}
}
impl Write for CanFdSocket {
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> IoResult<()> {
self.0.flush()
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CanFilter(libc::can_filter);
impl CanFilter {
pub fn new(id: canid_t, mask: canid_t) -> Self {
Self(libc::can_filter {
can_id: id,
can_mask: mask,
})
}
pub fn new_inverted(id: canid_t, mask: canid_t) -> Self {
Self::new(id | libc::CAN_INV_FILTER, mask)
}
}
impl From<libc::can_filter> for CanFilter {
fn from(filt: libc::can_filter) -> Self {
Self(filt)
}
}
impl From<(u32, u32)> for CanFilter {
fn from(filt: (u32, u32)) -> Self {
CanFilter::new(filt.0, filt.1)
}
}
impl AsRef<libc::can_filter> for CanFilter {
fn as_ref(&self) -> &libc::can_filter {
&self.0
}
}