|
7 | 7 | #define LOWLATSOCKET_H |
8 | 8 |
|
9 | 9 | #ifdef __linux__ |
10 | | -#include <iostream> |
11 | | -#endif //__linux__ |
12 | | - |
13 | | -#include <string> |
14 | | -#include <cstring> |
15 | | -#include <cassert> |
16 | | -#include <optional> |
17 | | -#include <cstdint> |
18 | | -#include <memory> |
19 | | - |
20 | | -#ifdef __linux__ |
21 | | -#include <linux/if_packet.h> |
22 | | -#include <linux/if_ether.h> |
23 | | -#include <netinet/in.h> |
24 | | -#include <net/if.h> |
25 | | -#include <unistd.h> |
26 | | -#include <sys/ioctl.h> |
27 | | -#else |
28 | | - |
29 | | -// Defining linux-like structs for compat |
30 | | -struct EthernetHeader { |
31 | | - uint8_t h_dest[6]; |
32 | | - uint8_t h_source[6]; |
33 | | - uint16_t h_proto; |
34 | | -} __attribute__((packed)); |
35 | | -typedef EthernetHeader ethhdr; |
36 | | - |
37 | | -#ifndef __ZEPHYR__ |
38 | | -#define htons(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)) |
39 | | -#else |
40 | | -#include "zephyr/net/net_ip.h" |
| 10 | +#include "platforms/lls_linux.h" |
| 11 | +#elif __ZEPHYR__ |
| 12 | +#include "platforms/lls_zephyr.h" |
41 | 13 | #endif |
42 | 14 |
|
43 | | -#endif //__linux__ |
44 | | - |
45 | | -/** |
46 | | - * @enum EthProtocol |
47 | | - * @brief Enum containing different values for the Ethernet protocol field, corresponding to different OAN stream types. |
48 | | - */ |
49 | | -enum EthProtocol : uint16_t { |
50 | | - ETH_PROTO_OANAUDIO = 0x0681, |
51 | | - ETH_PROTO_OANDISCO = 0x0682, |
52 | | - ETH_PROTO_OANCONTROL = 0x0683, |
53 | | - ETH_PROTO_OANSYNC = 0x0684 |
54 | | -}; |
55 | | - |
56 | | -/** |
57 | | - * @struct LowLatHeader |
58 | | - * @brief This header contains the layer 2 header of the protocol |
59 | | - */ |
60 | | -struct LowLatHeader { |
61 | | - uint16_t sender_uid; /**< Sender device UID */ |
62 | | - uint16_t dest_uid; /**< Receiver device UID */ |
63 | | - uint16_t psize; /**< Packet size */ |
64 | | -} __attribute__((packed)); |
65 | | - |
66 | | -/** |
67 | | - * @struct LowLatPacket |
68 | | - * @brief Layer 2 packet containing ethernet and addressing headers plus encapsulated data |
69 | | - * @tparam T Type of the encapsulated data |
70 | | - */ |
71 | | -template<class T> |
72 | | -struct LowLatPacket { |
73 | | - ethhdr eth_header; /**< Ethernet header, linux kernel structure */ |
74 | | - LowLatHeader llhdr; /**< LowLatHeader header, custom addressing scheme */ |
75 | | - T payload; /**< Encapsulated data */ |
76 | | -} __attribute__((packed)); |
77 | | - |
78 | | -/** |
79 | | - * @struct INT_LLP |
80 | | - * @brief Custom-sized LowLatPacket with no raw data for encapsulated data. For internal use only |
81 | | - * @tparam payload_size__ Custom size |
82 | | - */ |
83 | | -template<int payload_size__> |
84 | | -struct INT_LLP : public LowLatPacket<char[payload_size__]> {}; |
85 | | - |
86 | | -/** |
87 | | - * @struct IfaceMeta |
88 | | - * @brief This struct stores physical network interface info. |
89 | | - */ |
90 | | -struct IfaceMeta { |
91 | | - char mac[6]; /**< MAC Address */ |
92 | | - int idx; /**< Interface ID (kernel parameter) */ |
93 | | -}; |
94 | | - |
95 | | -/** |
96 | | - * Function to retreive a given network interface infos. |
97 | | - * @param name Interface name |
98 | | - * @return Interface infos if found. All zeros if not found. |
99 | | - */ |
100 | | -IfaceMeta get_iface_meta(const std::string& name); |
101 | | - |
102 | | -class NetworkMapper; |
103 | | - |
104 | | -/** |
105 | | - * @class LowLatSocket |
106 | | - * @brief Wrapper for raw sockets that implements a layer 2 addressing protocol. |
107 | | - */ |
108 | | -class LowLatSocket { |
109 | | -public: |
110 | | - /** |
111 | | - * Constructor |
112 | | - * @param self_uid Host UID |
113 | | - * @param mapper Local OAN network mapper |
114 | | - */ |
115 | | - LowLatSocket(uint16_t self_uid, std::shared_ptr<NetworkMapper> mapper); |
116 | | - ~LowLatSocket(); |
117 | | - |
118 | | - /** |
119 | | - * Initializes the socket |
120 | | - * @param interface Physical network interface name to attach the socket to |
121 | | - * @param proto Ethernet protocol used. @see EthProtocol |
122 | | - * @return true if initialization succeeds |
123 | | - */ |
124 | | - bool init_socket(std::string interface, EthProtocol proto); |
125 | | - |
126 | | - /** |
127 | | - * Format a given packet assuming it is a LowLatPacket<T> without sending it with the socket interface |
128 | | - * @param packet_buffer Packet buffer |
129 | | - * @param dest_uid Packet receiver UID |
130 | | - * @return true if successfully filled the header |
131 | | - */ |
132 | | - bool format_packet_header(uint8_t* packet_buffer, uint16_t dest_uid, size_t packet_size); |
133 | | - |
134 | | - /** |
135 | | - * Write in a given packet assuming it is a LowLatPacket<T> |
136 | | - * @param packet_buffer Packet buffer |
137 | | - * @param dest_uid Packet receiver UID |
138 | | - * @return true if successfully found MAC addr and wrote it to packet |
139 | | - */ |
140 | | - bool write_packet_mac_addr(uint8_t* packet_buffer, uint16_t dest_uid); |
141 | | - |
142 | | - /** |
143 | | - * Sends some data on the network |
144 | | - * @tparam T Sent data type |
145 | | - * @param data Pointer to the data |
146 | | - * @param dest_uid Package receiver UID |
147 | | - * @return Sent byte count. Less than 0 if error. |
148 | | - */ |
149 | | - template<class T> |
150 | | - int send_data(const T& data, uint16_t dest_uid) { |
151 | | - INT_LLP<sizeof(T)> llpck; |
152 | | - format_packet_header((uint8_t*)&llpck, dest_uid, sizeof(T)); |
153 | | - memcpy(llpck.payload, &data, sizeof(T)); |
154 | | - |
155 | | - if (dest_uid != 0) { |
156 | | - auto mac = get_mac(dest_uid); |
157 | | - if (mac.has_value()) { |
158 | | - uint64_t& v = mac.value(); |
159 | | - memcpy(llpck.eth_header.h_dest, &v, 6); |
160 | | - } else { |
161 | | - //std::cerr << "Trying to send data to unknown UID (" << (int)dest_uid << ")." << std::endl; |
162 | | - return 0; |
163 | | - } |
164 | | - } |
165 | | - |
166 | | -#ifdef __linux__ |
167 | | - return sendto( |
168 | | - m_socket, |
169 | | - &llpck, sizeof(llpck), |
170 | | - MSG_DONTWAIT, |
171 | | - (sockaddr*)&m_iface_addr, |
172 | | - sizeof(m_iface_addr) |
173 | | - ); |
174 | | -#else |
175 | | - return send_data_internal((uint8_t*)&llpck, sizeof(INT_LLP<sizeof(T)>)); |
176 | | -#endif // __linux__ |
177 | | - } |
178 | | - |
179 | | - /** |
180 | | - * Receive some data |
181 | | - * @tparam T Data type received |
182 | | - * @param data Pointer to the data buffer |
183 | | - * @param async This flag set the call as non-blocking if set to true |
184 | | - * @return Received byte count |
185 | | - */ |
186 | | - template<class T> |
187 | | - int receive_data(T* data, bool async = true) { |
188 | | -#ifdef __linux__ |
189 | | - return recv(m_socket, data, sizeof(T), async ? MSG_DONTWAIT : 0); |
190 | | -#else |
191 | | - return recv_data_internal((uint8_t*)data, sizeof(T)); |
192 | | -#endif // __linux__ |
193 | | - } |
194 | | - |
195 | | - /** |
196 | | - * Receive raw data. @see LowLatSocket::receive_data |
197 | | - * @param data Pointer to the data buffer |
198 | | - * @param size Amount of data expected |
199 | | - * @param async This flag set the call as non-blocking if set to true |
200 | | - * @return Received byte count |
201 | | - */ |
202 | | - int receive_data_raw(char* data, size_t size, bool async = true) const { |
203 | | -#ifdef __linux__ |
204 | | - return recv(m_socket, data, size, async ? MSG_DONTWAIT : 0); |
205 | | -#else |
206 | | - return recv_data_internal((uint8_t*)data, size); |
207 | | -#endif // __linux__ |
208 | | - } |
209 | | - |
210 | | - /** |
211 | | - * Send raw packet on wiore without further processing |
212 | | - * @param data Packet data |
213 | | - * @param size Packet size |
214 | | - * @return Number of byte sent |
215 | | - */ |
216 | | - int send_data_raw(char* data, size_t size) { |
217 | | - #ifdef __linux__ |
218 | | - return sendto( |
219 | | - m_socket, |
220 | | - data, size, |
221 | | - MSG_DONTWAIT, |
222 | | - (sockaddr*)&m_iface_addr, |
223 | | - sizeof(m_iface_addr) |
224 | | - ); |
225 | | - #else |
226 | | - return send_data_internal((uint8_t*)data, size); |
227 | | - #endif // __linux__ |
228 | | - } |
229 | | - |
230 | | -private: |
231 | | - /** |
232 | | - * Finds a device MAC address based on its ID. |
233 | | - * @param id ID to search for |
234 | | - * @return If found, the corresponding MAC address |
235 | | - */ |
236 | | - std::optional<uint64_t> get_mac(uint16_t id); |
237 | | - |
238 | | -#ifndef __linux__ |
239 | | - int send_data_internal(uint8_t* data, size_t size); |
240 | | - int recv_data_internal(uint8_t* data, size_t size) const; |
241 | | -#endif // __linux__ |
242 | | - |
243 | | -#ifdef __linux__ |
244 | | - sockaddr_ll m_iface_addr{}; |
245 | | -#else |
246 | | - uint8_t m_iface_addr[6]; |
247 | | -#endif // __linux__ |
248 | | - ethhdr m_hdr{}; |
249 | | - |
250 | | - int m_socket; |
251 | | - uint16_t m_self_uid; |
252 | | - EthProtocol m_self_proto; |
253 | | - |
254 | | - std::shared_ptr<NetworkMapper> m_mapper; |
255 | | -}; |
256 | | - |
257 | | - |
258 | | - |
259 | 15 | #endif //LOWLATSOCKET_H |
0 commit comments