marcelbuesing / socketcan-isotp

ISO-TP socketcan library for Rust
23 stars 12 forks source link

Unable to set timer for socket.read() function #4

Open rjsu26 opened 2 years ago

rjsu26 commented 2 years ago

I am trying to write a CAN based flashing script using rust where I can write and read some data. My problem here is that: I want to exit the system if say 5 seconds have elapsed without any response to the last request. Referring to the discussion of issue #2 and following the SO links there, I modified our library code from from :

setsockopt(
                    sock_fd,
                    SOL_CAN_ISOTP,
                    CAN_ISOTP_OPTS,
                    isotp_options_ptr,
                    ISOTP_OPTIONS_SIZE.try_into().unwrap(),
                )

to :

let mut tv = timeval { tv_sec: 5, tv_usec: 0 };
setsockopt(
                    sock_fd, 
                    SOL_CAN_ISOTP, 
                    SO_RCVTIMEO,
                    &tv as *const _ as *const c_void ,
                    size_of::<timeval>().try_into().unwrap()
                )

My compilation succeeded but during runtime I am facing the issue : "Err(Io { source: Os { code: 92, kind: Uncategorized, message: "Protocol not available" } })".

I need to implement this feature. Please guide me on doing this. Thanks

marcelbuesing commented 2 years ago

Hey, so my assumption is that is related directly to isotp kernel implementation. Maybe this helps: https://github.com/linux-can/can-utils/issues/82 I assume the alternative would be to basically create a thread for flashing and communicate the result via a channel, then use a recv_timeout on the receiver to handle a possible timeout.

fred314159265 commented 5 months ago

It's probably not much help to @rjsu26 at this point, but for anyone else coming across this thread, I have had success using the following, while keeping the original setsockopt's in place elsewhere.

Note: SOL_SOCKET instead of SOL_CAN_ISOTP.

let timeout = std::time::Duration::from_millis(1000);
let tv = nix::sys::time::TimeVal::new(
    timeout.as_secs() as i64,
    timeout.subsec_micros() as i64,
);
let err = unsafe {
    setsockopt(
        sock_fd,
        SOL_SOCKET,
        SO_RCVTIMEO,
        &tv as *const _ as *const c_void,
        size_of::<nix::sys::time::TimeVal>().try_into().unwrap(),
    )
};
if err == -1 {
    return Err(Error::from(io::Error::last_os_error()));
}
fred314159265 commented 5 months ago

FYI: #12