tokio_socketcan_isotp/
lib.rs1#![deny(clippy::all)]
2#![allow(dead_code)]
3mod socketcan_isotp;
42
43pub use crate::socketcan_isotp::{
44 Error, ExtendedId, FlowControlOptions, Id, IsoTpBehaviour, IsoTpOptions, LinkLayerOptions,
45 StandardId, TxFlags, AF_CAN, CAN_ISOTP, CAN_ISOTP_LL_OPTS, CAN_ISOTP_OPTS, CAN_ISOTP_RECV_FC,
46 CAN_ISOTP_RX_STMIN, CAN_ISOTP_TX_STMIN, CAN_MAX_DLEN, EFF_FLAG, EFF_MASK, ERR_FLAG, ERR_MASK,
47 ERR_MASK_ALL, ERR_MASK_NONE, PF_CAN, RECV_BUFFER_SIZE, RTR_FLAG, SFF_MASK, SOL_CAN_BASE,
48 SOL_CAN_ISOTP,
49};
50use futures::prelude::*;
51use futures::ready;
52use std::io;
53use std::os::raw::c_int;
54use std::pin::Pin;
55use std::task::{Context, Poll};
56use tokio::io::unix::AsyncFd;
57
58pub struct IsoTpWriteFuture<'a> {
60 socket: &'a IsoTpSocket,
61 packet: &'a [u8],
62}
63
64impl Future for IsoTpWriteFuture<'_> {
65 type Output = io::Result<()>;
66
67 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
68 loop {
69 let mut guard = ready!(self.socket.0.poll_write_ready(cx))?;
70 match self.socket.0.get_ref().write(self.packet) {
71 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
72 guard.clear_ready(); continue;
74 }
75 Ok(_) => return Poll::Ready(Ok(())),
76 Err(err) => return Poll::Ready(Err(err)),
77 }
78 }
79 }
80}
81
82pub struct IsoTpReadFuture<'a> {
84 socket: &'a IsoTpSocket,
85}
86
87impl Future for IsoTpReadFuture<'_> {
88 type Output = io::Result<Vec<u8>>;
89
90 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
91 loop {
92 let mut ready_guard = ready!(self.socket.0.poll_read_ready(cx))?;
93 match ready_guard.try_io(|inner| inner.get_ref().read_to_vec()) {
94 Ok(result) => return Poll::Ready(result),
95 Err(_would_block) => continue,
96 }
97 }
98 }
99}
100
101pub struct IsoTpSocket(AsyncFd<socketcan_isotp::IsoTpSocket>);
104#[allow(dead_code)]
105impl IsoTpSocket {
106 pub fn open(
108 ifname: &str,
109 src: impl Into<Id>,
110 dst: impl Into<Id>,
111 ) -> Result<IsoTpSocket, socketcan_isotp::Error> {
112 let sock = socketcan_isotp::IsoTpSocket::open(ifname, src, dst)?;
113 sock.set_nonblocking(true)?;
114 Ok(IsoTpSocket(AsyncFd::new(sock)?))
115 }
116
117 pub fn open_with_opts(
118 ifname: &str,
119 src: impl Into<Id>,
120 dst: impl Into<Id>,
121 isotp_options: Option<IsoTpOptions>,
122 rx_flow_control_options: Option<FlowControlOptions>,
123 link_layer_options: Option<LinkLayerOptions>,
124 ) -> Result<IsoTpSocket, socketcan_isotp::Error> {
125 let sock = socketcan_isotp::IsoTpSocket::open_with_opts(
126 ifname,
127 src,
128 dst,
129 isotp_options,
130 rx_flow_control_options,
131 link_layer_options,
132 )?;
133 sock.set_nonblocking(true)?;
134 Ok(IsoTpSocket(AsyncFd::new(sock)?))
135 }
136
137 pub fn open_if(
139 if_index: c_int,
140 src: impl Into<Id>,
141 dst: impl Into<Id>,
142 ) -> Result<IsoTpSocket, socketcan_isotp::Error> {
143 let sock = socketcan_isotp::IsoTpSocket::open_if(if_index, src, dst)?;
144 sock.set_nonblocking(true)?;
145 Ok(IsoTpSocket(AsyncFd::new(sock)?))
146 }
147
148 pub fn open_if_with_opts(
149 if_index: c_int,
150 src: impl Into<Id>,
151 dst: impl Into<Id>,
152 isotp_options: Option<IsoTpOptions>,
153 rx_flow_control_options: Option<FlowControlOptions>,
154 link_layer_options: Option<LinkLayerOptions>,
155 ) -> Result<IsoTpSocket, socketcan_isotp::Error> {
156 let sock = socketcan_isotp::IsoTpSocket::open_if_with_opts(
157 if_index,
158 src,
159 dst,
160 isotp_options,
161 rx_flow_control_options,
162 link_layer_options,
163 )?;
164 sock.set_nonblocking(true)?;
165 Ok(IsoTpSocket(AsyncFd::new(sock)?))
166 }
167
168 pub fn write_packet<'a>(&'a self, packet: &'a [u8]) -> IsoTpWriteFuture {
169 IsoTpWriteFuture {
170 socket: self,
171 packet,
172 }
173 }
174
175 pub fn read_packet(&self) -> IsoTpReadFuture {
176 IsoTpReadFuture { socket: self }
177 }
178}