13 #include <unordered_set>
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
21 #include <linux/can.h>
22 #include <linux/can/raw.h>
64 ::can_frame sockcan_frame = ::can_frame();
66 sockcan_frame.can_dlc = uavcan_frame.
dlc;
74 sockcan_frame.can_id |= CAN_ERR_FLAG;
78 sockcan_frame.can_id |= CAN_RTR_FLAG;
90 if (sockcan_frame.can_id & CAN_ERR_FLAG)
94 if (sockcan_frame.can_id & CAN_RTR_FLAG)
150 std::map<SocketCanError, std::uint64_t>
errors_;
194 const int res =
::write(
fd_, &sockcan_frame,
sizeof(sockcan_frame));
197 if (errno == ENOBUFS || errno == EAGAIN)
203 if (res !=
sizeof(sockcan_frame))
219 auto iov = ::iovec();
220 auto sockcan_frame = ::can_frame();
221 iov.iov_base = &sockcan_frame;
222 iov.iov_len =
sizeof(sockcan_frame);
224 static constexpr
size_t ControlSize =
sizeof(cmsghdr) +
sizeof(::timeval);
225 using ControlStorage =
typename std::aligned_storage<ControlSize>::type;
226 ControlStorage control_storage;
227 auto control =
reinterpret_cast<std::uint8_t *
>(&control_storage);
228 std::fill(control, control + ControlSize, 0x00);
230 auto msg = ::msghdr();
233 msg.msg_control = control;
234 msg.msg_controllen = ControlSize;
236 const int res = ::recvmsg(
fd_, &msg, MSG_DONTWAIT);
239 return (res < 0 && errno == EWOULDBLOCK) ? 0 : res;
244 loopback = (msg.msg_flags &
static_cast<int>(MSG_CONFIRM)) != 0;
255 const ::cmsghdr*
const cmsg = CMSG_FIRSTHDR(&msg);
256 assert(cmsg !=
nullptr);
257 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type ==
SO_TIMESTAMP)
259 auto tv = ::timeval();
260 (void)std::memcpy(&tv, CMSG_DATA(cmsg),
sizeof(tv));
261 assert(tv.tv_sec >= 0 && tv.tv_usec >= 0);
314 bool loopback =
false;
353 if (((
frame.can_id &
f.can_mask) ^
f.can_id) == 0)
419 out_frame = rx.
frame;
422 out_flags = rx.
flags;
454 if (filter_configs ==
nullptr)
462 for (
unsigned i = 0; i < num_configs; i++)
502 for (
auto& kv :
errors_) { ec += kv.second; }
522 const int s = ::socket(PF_CAN, SOCK_RAW,
CAN_RAW);
532 RaiiCloser(
int filedesc) :
fd_(filedesc)
544 void disarm() {
fd_ = -1; }
548 auto ifr = ::ifreq();
549 if (iface_name.length() >= IFNAMSIZ)
551 errno = ENAMETOOLONG;
554 (void)std::strncpy(ifr.ifr_name, iface_name.c_str(), iface_name.length());
555 if (::ioctl(
s, SIOCGIFINDEX, &ifr) < 0 || ifr.ifr_ifindex < 0)
562 auto addr = ::sockaddr_can();
564 addr.can_ifindex = ifr.ifr_ifindex;
565 if (::bind(
s,
reinterpret_cast<sockaddr*
>(&addr),
sizeof(addr)) < 0)
575 if (::setsockopt(
s, SOL_SOCKET,
SO_TIMESTAMP, &on,
sizeof(on)) < 0)
585 if (::fcntl(
s, F_SETFL, O_NONBLOCK) < 0)
593 int socket_error = 0;
594 ::socklen_t errlen =
sizeof(socket_error);
595 (void)::getsockopt(
s, SOL_SOCKET, SO_ERROR,
reinterpret_cast<void*
>(&socket_error), &errlen);
596 if (socket_error != 0)
598 errno = socket_error;
603 raii_closer.disarm();
629 assert(pfd.fd == this->getFileDescriptor());
630 if (!
down_ && (pfd.revents & POLLERR))
633 ::socklen_t errlen =
sizeof(
error);
634 (void)::getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR,
reinterpret_cast<void*
>(&
error), &errlen);
646 std::vector<std::unique_ptr<IfaceWrapper>>
ifaces_;
669 bool need_block = (inout_masks.
write == 0);
670 for (
unsigned i = 0; need_block && (i <
ifaces_.size()); i++)
672 const bool need_read = inout_masks.
read & (1 << i);
673 if (need_read &&
ifaces_[i]->hasReadyRx())
683 unsigned num_pollfds = 0;
686 for (
unsigned i = 0; i <
ifaces_.size(); i++)
690 pollfds[num_pollfds].fd =
ifaces_[i]->getFileDescriptor();
691 pollfds[num_pollfds].events = POLLIN;
692 if (
ifaces_[i]->hasReadyTx() || (inout_masks.
write & (1U << i)))
694 pollfds[num_pollfds].events |= POLLOUT;
696 pollfd_index_to_iface[num_pollfds] =
ifaces_[i].get();
702 if (num_pollfds == 0)
709 auto ts = ::timespec();
710 if (timeout_usec > 0)
712 ts.tv_sec = timeout_usec / 1000000LL;
713 ts.tv_nsec = (timeout_usec % 1000000LL) * 1000;
717 const int res = ::ppoll(pollfds, num_pollfds, &ts,
nullptr);
724 for (
unsigned i = 0; i < num_pollfds; i++)
728 const bool poll_read = pollfds[i].revents & POLLIN;
729 const bool poll_write = pollfds[i].revents & POLLOUT;
730 pollfd_index_to_iface[i]->
poll(poll_read, poll_write);
736 for (
unsigned i = 0; i <
ifaces_.size(); i++)
754 return (iface_index >=
ifaces_.size()) ? nullptr :
ifaces_[iface_index].get();
790 UAVCAN_TRACE(
"SocketCAN",
"New iface '%s' fd %d", iface_name.c_str(), fd);
800 return ifaces_.at(iface_index)->isDown();