simple-socket library 1.5.0
Loading...
Searching...
No Matches
CANSocket.cpp
1#include "CANSocket.h"
2
3#include <linux/can.h>
4#include <sys/socket.h>
5#include <sys/ioctl.h>
6#include <net/if.h>
7
8#include <cstring>
9#include <iomanip>
10#include <sstream>
11
12using namespace NET;
13
14CANSocket::CANSocket( int type, int protocol)
15: SimpleSocket( AF_CAN, type, protocol)
16{}
17
18void CANSocket::connect( std::string_view interface)
19{
20 sockaddr_can addr = {};
21 addr.can_family = AF_CAN;
22 addr.can_ifindex = getInterfaceIndex(interface);
23
24 if( ::connect( m_socket, (sockaddr*) &addr, sizeof(addr)) < 0)
25 throw SocketException("Connect failed (connect)");
26}
27
28void CANSocket::bind( std::string_view interface)
29{
30 sockaddr_can addr = {};
31 addr.can_family = AF_CAN;
32 addr.can_ifindex = getInterfaceIndex(interface);
33
34 if( ::bind( m_socket, (sockaddr*) &addr, sizeof(addr)) < 0)
35 throw SocketException("Set of interface failed (bind)");
36}
37
39{
40 sockaddr_can addr;
41 socklen_t addr_len = sizeof(addr);
42
43 if( ::getsockname( m_socket, (sockaddr*) &addr, &addr_len) < 0)
44 throw SocketException("Fetch of interface failed (getsockname)");
45
46 return getInterfaceName(addr);
47}
48
50{
51 sockaddr_can addr;
52 socklen_t addr_len = sizeof(addr);
53
54 if( ::getpeername( m_socket, (sockaddr*) &addr, &addr_len) < 0)
55 throw SocketException("Fetch of interface failed (getpeername)");
56
57 return getInterfaceName(addr);
58}
59
60std::string CANSocket::getInterfaceName( const sockaddr_can& addr) const
61{
62 struct ifreq ifr;
63 ifr.ifr_ifindex = addr.can_ifindex;
64
65 if( ioctl( m_socket, SIOCGIFNAME, &ifr) < 0)
66 throw SocketException("ioctl failed (getInterfaceName)");
67
68 return std::string(ifr.ifr_name);
69}
70
71int CANSocket::getInterfaceIndex( std::string_view interface) const
72{
73 const size_t len = interface.length();
74 // binds to all interfaces
75 if( len == 0) return 0;
76
77 // needed space is size plus null character
78 if( len >= IF_NAMESIZE)
79 throw SocketException("Interface name is too long", false);
80
81 struct ifreq ifr;
82 std::memcpy( ifr.ifr_name, interface.data(), len);
83 ifr.ifr_name[len] = 0;
84
85 if( ioctl( m_socket, SIOCGIFINDEX, &ifr) < 0)
86 throw SocketException("ioctl failed (getInterfaceIndex)");
87
88 return ifr.ifr_ifindex;
89}
90
91std::string CANSocket::formatCANID( canid_t can_id)
92{
93 std::ostringstream oss;
94 if( can_id & CAN_ERR_FLAG)
95 {
96 const canid_t error_mask = can_id & CAN_ERR_MASK;
97 oss << "ERR:0x"
98 << std::hex
99 << std::uppercase
100 << std::setw(8)
101 << std::setfill('0')
102 << error_mask;
103
104 return oss.str();
105 }
106
107 const bool extended = (can_id & CAN_EFF_FLAG) != 0;
108 const bool rtr = (can_id & CAN_RTR_FLAG) != 0;
109 const canid_t id =
110 can_id & (extended ? CAN_EFF_MASK : CAN_SFF_MASK);
111
112 oss << (extended ? "EFF:0x" : "SFF:0x")
113 << std::hex
114 << std::uppercase
115 << std::setw(extended ? 8 : 3)
116 << std::setfill('0')
117 << id;
118
119 if (rtr) oss << " RTR";
120
121 return oss.str();
122}
std::string getLocalInterface() const
Definition CANSocket.cpp:38
int getInterfaceIndex(std::string_view interface) const
get CAN interface index from interface name
Definition CANSocket.cpp:71
CANSocket(int type, int protocol)
allows a subclass to create new socket
Definition CANSocket.cpp:14
void bind(std::string_view interface="")
Definition CANSocket.cpp:28
static std::string formatCANID(::canid_t can_id)
format canid_t into string for logs
Definition CANSocket.cpp:91
std::string getInterfaceName(const sockaddr_can &addr) const
get CAN interface name from socket address structure
Definition CANSocket.cpp:60
std::string getForeignInterface() const
Definition CANSocket.cpp:49
void connect(std::string_view interface="")
Definition CANSocket.cpp:18
Signals a problem with the execution of a socket call.