join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
datagram_socket.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_DATAGRAM_SOCKET_HPP
26#define JOIN_CORE_DATAGRAM_SOCKET_HPP
27
28// libjoin.
29#include <join/raw_socket.hpp>
30
31// C.
32#include <cstring>
33
34namespace join
35{
39 template <class Protocol>
40 class BasicDatagramSocket final : public BasicRawSocket<Protocol>
41 {
42 public:
43 using Ptr = std::unique_ptr<BasicDatagramSocket<Protocol>>;
47 using Endpoint = typename Protocol::Endpoint;
48
56
61 explicit BasicDatagramSocket (int ttl) noexcept
62 : BasicDatagramSocket (Mode::NonBlocking, ttl)
63 {
64 }
65
71 explicit BasicDatagramSocket (Mode mode, int ttl = 60) noexcept
72 : BasicRawSocket<Protocol> (mode)
73 , _ttl (ttl)
74 {
75 }
76
82
89
95 : BasicRawSocket<Protocol> (std::move (other))
96 , _remote (std::move (other._remote))
97 , _ttl (other._ttl)
98 {
99 other._ttl = 60;
100 }
101
108 {
109 BasicRawSocket<Protocol>::operator= (std::move (other));
110
111 _remote = std::move (other._remote);
112 _ttl = other._ttl;
113
114 other._ttl = 60;
115
116 return *this;
117 }
118
123
129 int open (const Protocol& protocol = Protocol ()) noexcept override
130 {
132 if (result == -1)
133 {
134 return -1;
135 }
136
137 int off = 0;
138
139 if ((protocol.protocol () == IPPROTO_UDP) || (protocol.protocol () == IPPROTO_TCP))
140 {
141 if ((protocol.family () == AF_INET6) &&
142 (::setsockopt (this->_handle, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof (off)) == -1))
143 {
144 // LCOV_EXCL_START
145 lastError = std::error_code (errno, std::generic_category ());
146 close ();
147 return -1;
148 // LCOV_EXCL_STOP
149 }
150 }
151
152 if ((protocol.protocol () == IPPROTO_ICMPV6) || (protocol.protocol () == IPPROTO_ICMP))
153 {
154 if ((protocol.family () == AF_INET) &&
155 (::setsockopt (this->_handle, IPPROTO_IP, IP_HDRINCL, &off, sizeof (off)) == -1))
156 {
157 // LCOV_EXCL_START
158 lastError = std::error_code (errno, std::generic_category ());
159 close ();
160 return -1;
161 // LCOV_EXCL_STOP
162 }
163
164 this->setOption (Option::MulticastTtl, _ttl);
165 this->setOption (Option::Ttl, _ttl);
166 }
167
168 return 0;
169 }
170
178 int connect (const Endpoint& endpoint) noexcept
179 {
180 if ((this->_state != State::Closed) && (this->_state != State::Disconnected))
181 {
182 lastError = make_error_code (Errc::InUse);
183 return -1;
184 }
185
186 if ((this->_state == State::Closed) && (open (endpoint.protocol ()) == -1))
187 {
188 return -1; // LCOV_EXCL_LINE
189 }
190
191 if (::connect (this->_handle, endpoint.addr (), endpoint.length ()) == -1)
192 {
193 lastError = std::error_code (errno, std::generic_category ());
194 close ();
195 return -1;
196 }
197
198 _remote = endpoint;
199 this->_state = State::Connected;
200
201 return 0;
202 }
203
208 int disconnect () noexcept
209 {
210 if (this->_state == State::Connected)
211 {
212 struct sockaddr_storage nullAddr;
213 ::memset (&nullAddr, 0, sizeof (nullAddr));
214
215 nullAddr.ss_family = AF_UNSPEC;
216
217 int result = ::connect (this->_handle, reinterpret_cast<struct sockaddr*> (&nullAddr),
218 sizeof (struct sockaddr_storage));
219 if (result == -1)
220 {
221 // LCOV_EXCL_START
222 if (errno != EAFNOSUPPORT)
223 {
224 lastError = std::error_code (errno, std::generic_category ());
225 return -1;
226 }
227 // LCOV_EXCL_STOP
228 }
229
230 this->_state = State::Disconnected;
231 _remote = {};
232 }
233
234 return 0;
235 }
236
240 void close () noexcept override
241 {
243 _remote = {};
244 }
245
255 ssize_t readFrom (char* data, size_t maxSize, Endpoint* endpoint = nullptr, char* control = nullptr,
256 size_t* controlSize = nullptr) noexcept
257 {
258 struct sockaddr_storage sa;
259
260 struct iovec iov;
261 iov.iov_base = data;
262 iov.iov_len = maxSize;
263
264 struct msghdr message;
265 message.msg_name = &sa;
266 message.msg_namelen = sizeof (struct sockaddr_storage);
267 message.msg_iov = &iov;
268 message.msg_iovlen = 1;
269 message.msg_control = control;
270 message.msg_controllen = controlSize ? *controlSize : 0;
271
272 ssize_t size = ::recvmsg (this->_handle, &message, 0);
273 if (size == -1)
274 {
275 lastError = std::error_code (errno, std::generic_category ());
276 return -1;
277 }
278
279 if (message.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
280 {
282 return -1;
283 }
284
285 if (endpoint != nullptr)
286 {
287 *endpoint = Endpoint (reinterpret_cast<struct sockaddr*> (&sa), message.msg_namelen);
288 }
289
290 if (controlSize != nullptr)
291 {
292 *controlSize = message.msg_controllen;
293 }
294
295 return size;
296 }
297
307 ssize_t writeTo (const char* data, size_t size, const Endpoint& endpoint, const char* control = nullptr,
308 size_t controlSize = 0) noexcept
309 {
310 if ((this->_state == State::Closed) && (open (endpoint.protocol ()) == -1))
311 {
312 return -1; // LCOV_EXCL_LINE
313 }
314
315 struct iovec iov;
316 iov.iov_base = const_cast<char*> (data);
317 iov.iov_len = size;
318
319 struct msghdr message;
320 message.msg_name = const_cast<struct sockaddr*> (endpoint.addr ());
321 message.msg_namelen = endpoint.length ();
322 message.msg_iov = &iov;
323 message.msg_iovlen = 1;
324 message.msg_control = const_cast<char*> (control);
325 message.msg_controllen = controlSize;
326 message.msg_flags = 0;
327
328 ssize_t result = ::sendmsg (this->_handle, &message, 0);
329 if (result < 0)
330 {
331 lastError = std::error_code (errno, std::generic_category ());
332 return -1;
333 }
334
335 return result;
336 }
337
342 const Endpoint& remoteEndpoint () const noexcept
343 {
344 return _remote;
345 }
346
351 bool connected () const noexcept
352 {
353 return (this->_state == State::Connected);
354 }
355
360 int mtu () const noexcept
361 {
362 if (this->_state == State::Closed)
363 {
365 return -1;
366 }
367
368 int result = -1, value = -1;
369 socklen_t valueLen = sizeof (value);
370
371 if (this->family () == AF_INET6)
372 {
373 result = ::getsockopt (this->_handle, IPPROTO_IPV6, IPV6_MTU, &value, &valueLen);
374 }
375 else if (this->family () == AF_INET)
376 {
377 result = ::getsockopt (this->_handle, IPPROTO_IP, IP_MTU, &value, &valueLen);
378 }
379 else
380 {
382 return -1;
383 }
384
385 if (result == -1)
386 {
387 lastError = std::error_code (errno, std::generic_category ());
388 return -1;
389 }
390
391 return value;
392 }
393
398 int ttl () const noexcept
399 {
400 return _ttl;
401 }
402
403 protected:
406
408 int _ttl = 60;
409 };
410}
411
412#endif
basic datagram socket class.
Definition protocol.hpp:50
typename BasicRawSocket< Protocol >::Option Option
Definition datagram_socket.hpp:45
bool connected() const noexcept
check if the socket is connected.
Definition datagram_socket.hpp:351
BasicDatagramSocket(const BasicDatagramSocket &other)=delete
Copy constructor.
ssize_t writeTo(const char *data, size_t size, const Endpoint &endpoint, const char *control=nullptr, size_t controlSize=0) noexcept
write data on the socket.
Definition datagram_socket.hpp:307
const Endpoint & remoteEndpoint() const noexcept
determine the remote endpoint associated with this socket.
Definition datagram_socket.hpp:342
int mtu() const noexcept
get socket mtu.
Definition datagram_socket.hpp:360
std::unique_ptr< BasicDatagramSocket< Protocol > > Ptr
Definition datagram_socket.hpp:43
int disconnect() noexcept
remove the default remote endpoint.
Definition datagram_socket.hpp:208
Endpoint _remote
remote endpoint.
Definition datagram_socket.hpp:405
typename BasicRawSocket< Protocol >::Mode Mode
Definition datagram_socket.hpp:44
int _ttl
packet time to live.
Definition datagram_socket.hpp:408
typename BasicRawSocket< Protocol >::State State
Definition datagram_socket.hpp:46
BasicDatagramSocket() noexcept
Default constructor.
Definition datagram_socket.hpp:52
~BasicDatagramSocket()=default
Destroy the instance.
typename Protocol::Endpoint Endpoint
Definition datagram_socket.hpp:47
void close() noexcept override
close the socket handle.
Definition datagram_socket.hpp:240
ssize_t readFrom(char *data, size_t maxSize, Endpoint *endpoint=nullptr, char *control=nullptr, size_t *controlSize=nullptr) noexcept
read data on the socket.
Definition datagram_socket.hpp:255
int connect(const Endpoint &endpoint) noexcept
assign the default remote endpoint for this socket.
Definition datagram_socket.hpp:178
BasicDatagramSocket & operator=(const BasicDatagramSocket &other)=delete
Copy assignment operator.
BasicDatagramSocket(BasicDatagramSocket &&other) noexcept
Move constructor.
Definition datagram_socket.hpp:94
BasicDatagramSocket(int ttl) noexcept
Create instance specifying the time to live.
Definition datagram_socket.hpp:61
int ttl() const noexcept
returns the Time-To-Live value.
Definition datagram_socket.hpp:398
BasicDatagramSocket(Mode mode, int ttl=60) noexcept
Create instance specifying the mode.
Definition datagram_socket.hpp:71
int open(const Protocol &protocol=Protocol()) noexcept override
open socket using the given protocol.
Definition datagram_socket.hpp:129
basic raw socket class.
Definition raw_socket.hpp:42
typename BasicSocket< Protocol >::Mode Mode
Definition raw_socket.hpp:45
typename BasicSocket< Protocol >::State State
Definition raw_socket.hpp:46
Option
socket options.
Definition raw_socket.hpp:53
BasicRawSocket & operator=(const BasicRawSocket &other)=delete
copy assignment operator.
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
virtual int open(const Protocol &protocol=Protocol()) noexcept
open socket using the given protocol.
Definition socket.hpp:168
Mode mode() const noexcept
get the blocking mode of the socket.
Definition socket.hpp:374
virtual void close() noexcept
close the socket.
Definition socket.hpp:203
int family() const noexcept
get socket address family.
Definition socket.hpp:347
@ NonBlocking
Definition socket.hpp:69
State _state
socket state.
Definition socket.hpp:468
int protocol() const noexcept
get socket protocol.
Definition socket.hpp:365
int _handle
socket handle.
Definition socket.hpp:474
Definition acceptor.hpp:32
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195