join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
raw_socket.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_RAW_SOCKET_HPP
26#define JOIN_CORE_RAW_SOCKET_HPP
27
28// libjoin.
29#include <join/socket.hpp>
30
31// C.
32#include <netinet/tcp.h>
33#include <sys/ioctl.h>
34
35namespace join
36{
40 template <class Protocol>
41 class BasicRawSocket : public BasicSocket<Protocol>
42 {
43 public:
44 using Ptr = std::unique_ptr<BasicRawSocket<Protocol>>;
47 using Endpoint = typename Protocol::Endpoint;
48
72
76 BasicRawSocket () noexcept
78 {
79 }
80
85 explicit BasicRawSocket (Mode mode) noexcept
87 {
88 }
89
94 BasicRawSocket (const BasicRawSocket& other) = delete;
95
101 BasicRawSocket& operator= (const BasicRawSocket& other) = delete;
102
107 BasicRawSocket (BasicRawSocket&& other) noexcept = default;
108
114 BasicRawSocket& operator= (BasicRawSocket&& other) noexcept = default;
115
119 virtual ~BasicRawSocket () = default;
120
126 int bind (const Endpoint& endpoint) noexcept override
127 {
128 if ((this->_state == State::Closed) && (this->open (endpoint.protocol ()) == -1))
129 {
130 return -1; // LCOV_EXCL_LINE
131 }
132
133 if (endpoint.protocol ().family () == AF_PACKET)
134 {
135 if (reinterpret_cast<const struct sockaddr_ll*> (endpoint.addr ())->sll_ifindex == 0)
136 {
137 lastError = std::make_error_code (std::errc::no_such_device);
138 return -1;
139 }
140 }
141 else if ((endpoint.protocol ().family () == AF_INET6) || (endpoint.protocol ().family () == AF_INET))
142 {
144 }
145 else if (endpoint.protocol ().family () == AF_UNIX)
146 {
147 ::unlink (endpoint.device ().c_str ());
148 }
149
150 return BasicSocket<Protocol>::bind (endpoint);
151 }
152
158 int bindToDevice (const std::string& device) noexcept
159 {
160 if (this->_state == State::Closed)
161 {
163 return -1;
164 }
165
166 if (this->_state == State::Connected)
167 {
168 lastError = make_error_code (Errc::InUse);
169 return -1;
170 }
171
172 if ((this->family () == AF_INET6) || (this->family () == AF_INET))
173 {
175 }
176
177 int result = ::setsockopt (this->_handle, SOL_SOCKET, SO_BINDTODEVICE, device.c_str (), device.size ());
178 if (result == -1)
179 {
180 lastError = std::error_code (errno, std::generic_category ());
181 return -1;
182 }
183
184 return 0;
185 }
186
191 ssize_t canRead () const noexcept
192 {
193 int available = 0;
194
195 // check if data can be read in the socket internal buffer.
196 if (::ioctl (this->_handle, FIONREAD, &available) == -1)
197 {
198 lastError = std::error_code (errno, std::generic_category ());
199 return -1;
200 }
201
202 return available;
203 }
204
211 ssize_t read (char* data, size_t maxSize) noexcept
212 {
213 struct iovec iov;
214 iov.iov_base = data;
215 iov.iov_len = maxSize;
216
217 struct msghdr message;
218 message.msg_name = nullptr;
219 message.msg_namelen = 0;
220 message.msg_iov = &iov;
221 message.msg_iovlen = 1;
222 message.msg_control = nullptr;
223 message.msg_controllen = 0;
224
225 ssize_t size = ::recvmsg (this->_handle, &message, 0);
226 if (size == -1)
227 {
228 lastError = std::error_code (errno, std::generic_category ());
229 return -1;
230 }
231
232 if (message.msg_flags & MSG_TRUNC)
233 {
235 return -1;
236 }
237
238 return size;
239 }
240
247 ssize_t write (const char* data, size_t maxSize) noexcept
248 {
249 struct iovec iov;
250 iov.iov_base = const_cast<char*> (data);
251 iov.iov_len = maxSize;
252
253 struct msghdr message;
254 message.msg_name = nullptr;
255 message.msg_namelen = 0;
256 message.msg_iov = &iov;
257 message.msg_iovlen = 1;
258 message.msg_control = nullptr;
259 message.msg_controllen = 0;
260
261 ssize_t result = ::sendmsg (this->_handle, &message, 0);
262 if (result == -1)
263 {
264 lastError = std::error_code (errno, std::generic_category ());
265 return -1;
266 }
267
268 return result;
269 }
270
277 virtual int setOption (Option option, int value) noexcept
278 {
279 int optlevel, optname;
280
281 switch (option)
282 {
284 optlevel = SOL_SOCKET;
285 optname = SO_KEEPALIVE;
286 break;
287
289 optlevel = SOL_SOCKET;
290 optname = SO_SNDBUF;
291 break;
292
294 optlevel = SOL_SOCKET;
295 optname = SO_RCVBUF;
296 break;
297
299 optlevel = SOL_SOCKET;
300 optname = SO_TIMESTAMP;
301 break;
302
304 optlevel = SOL_SOCKET;
305 optname = SO_REUSEADDR;
306 break;
307
309 optlevel = SOL_SOCKET;
310 optname = SO_REUSEPORT;
311 break;
312
314 optlevel = SOL_SOCKET;
315 optname = SO_BROADCAST;
316 break;
317
318 case Option::AuxData:
319 optlevel = SOL_PACKET;
320 optname = PACKET_AUXDATA;
321 break;
322
323 case Option::Ttl:
324 if (this->family () == AF_INET6)
325 {
326 optlevel = IPPROTO_IPV6;
327 optname = IPV6_UNICAST_HOPS;
328 }
329 else
330 {
331 optlevel = IPPROTO_IP;
332 optname = IP_TTL;
333 }
334 break;
335
337 if (this->family () == AF_INET6)
338 {
339 optlevel = IPPROTO_IPV6;
340 optname = IPV6_MULTICAST_LOOP;
341 }
342 else
343 {
344 optlevel = IPPROTO_IP;
345 optname = IP_MULTICAST_LOOP;
346 }
347 break;
348
350 if (this->family () == AF_INET6)
351 {
352 optlevel = IPPROTO_IPV6;
353 optname = IPV6_MULTICAST_HOPS;
354 }
355 else
356 {
357 optlevel = IPPROTO_IP;
358 optname = IP_MULTICAST_TTL;
359 }
360 break;
361
363 if (this->family () == AF_INET6)
364 {
365 optlevel = IPPROTO_IPV6;
366 optname = IPV6_MTU_DISCOVER;
367 }
368 else
369 {
370 optlevel = IPPROTO_IP;
371 optname = IP_MTU_DISCOVER;
372 }
373 break;
374
375 case Option::RcvError:
376 if (this->family () == AF_INET6)
377 {
378 optlevel = IPPROTO_IPV6;
379 optname = IPV6_RECVERR;
380 }
381 else
382 {
383 optlevel = IPPROTO_IP;
384 optname = IP_RECVERR;
385 }
386 break;
387
388 default:
390 return -1;
391 }
392
393 int result = ::setsockopt (this->_handle, optlevel, optname, &value, sizeof (value));
394 if (result == -1)
395 {
396 lastError = std::error_code (errno, std::generic_category ());
397 return -1;
398 }
399
400 return 0;
401 }
402 };
403}
404
405#endif
basic raw socket class.
Definition raw_socket.hpp:42
std::unique_ptr< BasicRawSocket< Protocol > > Ptr
Definition raw_socket.hpp:44
int bindToDevice(const std::string &device) noexcept
assigns the specified device to the socket.
Definition raw_socket.hpp:158
typename BasicSocket< Protocol >::Mode Mode
Definition raw_socket.hpp:45
BasicRawSocket(const BasicRawSocket &other)=delete
copy constructor.
ssize_t write(const char *data, size_t maxSize) noexcept
write data.
Definition raw_socket.hpp:247
typename BasicSocket< Protocol >::State State
Definition raw_socket.hpp:46
Option
socket options.
Definition raw_socket.hpp:53
@ Ttl
Definition raw_socket.hpp:65
@ RcvBuffer
Definition raw_socket.hpp:60
@ MulticastTtl
Definition raw_socket.hpp:67
@ TimeStamp
Definition raw_socket.hpp:61
@ KeepIntvl
Definition raw_socket.hpp:57
@ NoDelay
Definition raw_socket.hpp:54
@ Broadcast
Definition raw_socket.hpp:64
@ SndBuffer
Definition raw_socket.hpp:59
@ PathMtuDiscover
Definition raw_socket.hpp:68
@ ReusePort
Definition raw_socket.hpp:63
@ RcvError
Definition raw_socket.hpp:69
@ ReuseAddr
Definition raw_socket.hpp:62
@ MulticastLoop
Definition raw_socket.hpp:66
@ AuxData
Definition raw_socket.hpp:70
@ KeepCount
Definition raw_socket.hpp:58
@ KeepAlive
Definition raw_socket.hpp:55
@ KeepIdle
Definition raw_socket.hpp:56
BasicRawSocket(BasicRawSocket &&other) noexcept=default
move constructor.
ssize_t canRead() const noexcept
get the number of readable bytes.
Definition raw_socket.hpp:191
BasicRawSocket & operator=(const BasicRawSocket &other)=delete
copy assignment operator.
virtual ~BasicRawSocket()=default
destroy the socket instance.
typename Protocol::Endpoint Endpoint
Definition raw_socket.hpp:47
ssize_t read(char *data, size_t maxSize) noexcept
read data.
Definition raw_socket.hpp:211
virtual int setOption(Option option, int value) noexcept
set the given option to the given value.
Definition raw_socket.hpp:277
BasicRawSocket() noexcept
default constructor.
Definition raw_socket.hpp:76
BasicRawSocket(Mode mode) noexcept
create socket instance specifying the mode.
Definition raw_socket.hpp:85
int bind(const Endpoint &endpoint) noexcept override
assigns the specified endpoint to the socket.
Definition raw_socket.hpp:126
basic socket class.
Definition socket.hpp:52
virtual int open(const Protocol &protocol=Protocol()) noexcept
open socket using the given protocol.
Definition socket.hpp:167
Mode mode() const noexcept
get the blocking mode of the socket.
Definition socket.hpp:373
State
socket states.
Definition socket.hpp:75
int family() const noexcept
get socket address family.
Definition socket.hpp:346
Mode
socket modes.
Definition socket.hpp:66
@ NonBlocking
Definition socket.hpp:68
virtual int bind(const Endpoint &endpoint) noexcept
assigns the specified endpoint to the socket.
Definition socket.hpp:217
State _state
socket state.
Definition socket.hpp:467
BasicSocket() noexcept
default constructor.
Definition socket.hpp:86
int _handle
socket handle.
Definition socket.hpp:473
Definition acceptor.hpp:32
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195