MLIB
Loading...
Searching...
No Matches
sock.h
1#pragma once
2
3#if __has_include("defs.h")
4#include "defs.h"
5#endif
6
7#include "safe_winsock.h"
8#include "errorcode.h"
9#include "inaddr.h"
10#include "tvops.h"
11
12namespace mlib {
13
14// clang-format off
18class sock
19{
20public:
22 enum type
23 {
24 stream = SOCK_STREAM,
25 dgram = SOCK_DGRAM,
26 raw = SOCK_RAW
27 };
28
31 {
35 };
36
38 enum mflags
39 {
40 none = 0,
41 out_of_band = MSG_OOB,
42 peek = MSG_PEEK,
43 dont_route = MSG_DONTROUTE,
44 wait_all = MSG_WAITALL
45 };
46
47 sock ();
48 explicit sock (SOCKET soc);
49 explicit sock (type t, int domain = AF_INET, int proto = 0);
50 sock (const sock&);
51 sock (sock&&);
52
53 virtual ~sock ();
54 sock& operator= (const sock&);
56 HANDLE handle () const;
57 bool operator== (const sock& other) const;
58 bool operator!= (const sock& other) const;
59 operator SOCKET () const;
60
61 virtual erc open (type t, int domain = AF_INET, int proto = 0);
62 virtual void close ();
63 virtual erc shutdown (shuthow sh) const;
64
65 virtual bool is_open () const;
66 size_t recv (void* buf, size_t maxlen, mflags msgf = mflags::none) const;
67 size_t recvfrom (sockaddr& sa, void* buf, size_t maxlen, mflags msgf = mflags::none) const;
68 size_t send (const void* buf, size_t len, mflags msgf = mflags::none) const;
69 template <typename T>
70 size_t send (std::basic_string<T> buf, mflags msgf = mflags::none) const;
71 size_t sendto (const sockaddr& sa, const void* buf, size_t len, mflags msgf = mflags::none) const;
72 template <typename T>
73 size_t sendto (const sockaddr& sa, std::basic_string<T> buf, mflags msgf = mflags::none) const;
74
75 void sendtimeout (std::chrono::milliseconds tmo) const;
76 std::chrono::milliseconds sendtimeout () const;
77 void recvtimeout (std::chrono::milliseconds tmo) const;
78 std::chrono::milliseconds recvtimeout () const;
79 bool is_readready (std::chrono::milliseconds tmo = std::chrono::milliseconds{0}) const;
80 bool is_writeready (std::chrono::milliseconds tmo = std::chrono::milliseconds{0}) const;
81 bool is_exceptionpending (std::chrono::milliseconds tmo = std::chrono::milliseconds{0}) const;
82 unsigned int nread () const;
83
84 erc bind (const inaddr&) const;
85 erc bind () const;
86 erc connect (const inaddr& peer) const;
87 erc connect (const inaddr& peer, std::chrono::milliseconds tmo) const;
88 bool connected () const;
89 erc listen (int num = SOMAXCONN) const;
90 erc accept (sock& client, inaddr* sa = nullptr) const;
91 erc accept (sock& client, std::chrono::milliseconds tmo, inaddr* sa = nullptr) const;
92 checked<inaddr> name () const;
93 checked<inaddr> peer () const;
94
95 int getopt (int op, void* buf, int len, int level = SOL_SOCKET) const;
96 erc setopt (int op, void* buf, int len, int level = SOL_SOCKET) const;
97
98 int gettype () const;
99 int clearerror () const;
100 bool debug () const;
101 void debug (bool opt) const;
102 bool reuseaddr () const;
103 void reuseaddr (bool opt) const;
104 bool keepalive () const;
105 void keepalive (bool opt) const;
106 bool dontroute () const;
107 void dontroute (bool opt) const;
108 bool broadcast () const;
109 void broadcast (bool opt) const;
110 bool oobinline () const;
111 void oobinline (bool opt) const;
112 int sendbufsz () const;
113 void sendbufsz (size_t sz) const;
114 int recvbufsz () const;
115 void recvbufsz (size_t sz) const;
116 void blocking (bool on_off);
117#ifdef _WIN32
118 erc setevent (HANDLE evt, long mask) const;
119 long enumevents () const;
120#endif
121 void linger (bool on_off, unsigned short seconds) const;
122 bool linger (unsigned short* seconds = 0) const;
123 void nodelay (bool on_off);
124 bool nodelay () const;
125
127 static errfac& Errors ();
128
130 static void Errors (errfac& facitlity);
131
132protected:
133 static erc last_error ();
134
135private:
136 struct sock_ref
137 {
138 sock_ref ()
139 : handle{INVALID_SOCKET}
140 , ref_count{1} {};
141 SOCKET handle;
142 int ref_count;
143 }* sl;
144
145 friend class inaddr;
146 friend struct sock_initializer;
147};
148
149/*---------------------- support classes ------------------------------------*/
152static struct sock_initializer
153{
154 sock_initializer ();
155 ~sock_initializer ();
156} sock_nifty_counter;
157
158
159/*==================== INLINE FUNCTIONS ===========================*/
160
162inline
164 : sl{nullptr}
165{}
166
168inline
169HANDLE sock::handle () const
170{
171 return sl ? (HANDLE)(std::intptr_t)sl->handle : INVALID_HANDLE_VALUE;
172}
173
175inline
176sock::operator SOCKET () const
177{
178 return sl ? sl->handle : INVALID_SOCKET;
179}
180
182inline
183bool sock::is_open () const
184{
185 return sl && sl->handle != INVALID_SOCKET;
186}
187
189inline
190erc sock::connect (const inaddr& peer) const
191{
192 if (!sl || sl->handle == INVALID_SOCKET)
193 return erc (WSAENOTSOCK, Errors());
194
195 int ret = ::connect (sl->handle, peer, sizeof (peer));
196 if (ret == INVALID_SOCKET)
197 return last_error ();
198
199 return erc::success;
200}
201
203inline
204bool sock::connected () const
205{
206 return is_writeready ();
207}
208
210inline
211erc sock::accept (sock& client, inaddr* addr) const
212{
213 if (!sl || sl->handle == INVALID_SOCKET)
214 return erc (WSAENOTSOCK, Errors());
215
216 sockaddr sa;
217 socklen_t len = sizeof (sa);
218 client = sock (::accept (sl->handle, &sa, &len));
219 if (addr)
220 *addr = sa;
221 return erc ();
222}
223
225inline
226erc sock::listen (int num) const
227{
228 if (!sl || sl->handle == INVALID_SOCKET)
229 return erc (WSAENOTSOCK, Errors());
230
231 ::listen (sl->handle, num);
232 return last_error ();
233}
234
243template <typename T>
244size_t sock::send (std::basic_string<T> buf, mflags msgf) const
245{
246 return send (buf.c_str (), buf.size () * sizeof (T), msgf);
247}
248
258template <typename T>
259size_t sock::sendto (const sockaddr& sa, std::basic_string<T> buf, mflags msgf) const
260{
261 return sendto (sa, buf.c_str (), buf.size () * sizeof (T), msgf);
262}
263
268inline
269void sock::sendtimeout (std::chrono::milliseconds tmo) const
270{
271 assert (sl && sl->handle != INVALID_SOCKET);
272
273#ifdef _WIN32
274 socklen_t optlen = sizeof (int);
275 int par = (int)tmo.count();
276#else
277 socklen_t optlen = sizeof(timeval);
278 timeval par = from_chrono (tmo);
279#endif
280 setsockopt (sl->handle, SOL_SOCKET, SO_SNDTIMEO, (char*)&par, optlen);
281}
282
284inline
285std::chrono::milliseconds sock::sendtimeout () const
286{
287 assert (sl && sl->handle != INVALID_SOCKET);
288
289#ifdef _WIN32
290 socklen_t optlen = sizeof (int);
291 int tmo;
292 getsockopt (sl->handle, SOL_SOCKET, SO_SNDTIMEO, (char*)&tmo, &optlen);
293 return std::chrono::milliseconds(tmo);
294#else
295 socklen_t optlen = sizeof(timeval);
296 timeval tv;
297 getsockopt (sl->handle, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, &optlen);
298 return std::chrono::duration_cast<std::chrono::milliseconds>(to_chrono (tv));
299#endif
300}
301
306inline
307void sock::recvtimeout (std::chrono::milliseconds tmo) const
308{
309 assert (sl && sl->handle != INVALID_SOCKET);
310#ifdef _WIN32
311 socklen_t optlen = sizeof (int);
312 int par = (int)tmo.count();
313#else
314 socklen_t optlen = sizeof(timeval);
315 timeval par = from_chrono (tmo);
316#endif
317 setsockopt (sl->handle, SOL_SOCKET, SO_RCVTIMEO, (char*)&par, optlen);
318}
319
321inline
322std::chrono::milliseconds sock::recvtimeout () const
323{
324 assert (sl && sl->handle != INVALID_SOCKET);
325#ifdef _WIN32
326 socklen_t optlen = sizeof (int);
327 int tmo;
328 getsockopt (sl->handle, SOL_SOCKET, SO_RCVTIMEO, (char*)&tmo, &optlen);
329 return std::chrono::milliseconds (tmo);
330#else
331 socklen_t optlen = sizeof(timeval);
332 timeval tv;
333 getsockopt (sl->handle, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, &optlen);
334 return std::chrono::duration_cast<std::chrono::milliseconds> (to_chrono(tv));
335#endif
336}
337
347inline
348int sock::getopt (int op, void* buf, int len, int level) const
349{
350 if (!sl || sl->handle == INVALID_SOCKET)
351 return erc (WSAENOTSOCK, Errors());
352
353 socklen_t rlen = len;
354 if (::getsockopt (sl->handle, level, op, (char*)buf, &rlen) == SOCKET_ERROR)
355 last_error ().raise ();
356 return rlen;
357}
358
366inline
367erc sock::setopt (int op, void* buf, int len, int level) const
368{
369 if (!sl || sl->handle == INVALID_SOCKET)
370 return erc (WSAENOTSOCK, Errors());
371
372 if (::setsockopt (sl->handle, level, op, (char*)buf, len) == SOCKET_ERROR)
373 return last_error ();
374
375 return erc::success;
376}
377
381inline
382int sock::gettype () const
383{
384 int ty = 0;
385 getopt (SO_TYPE, &ty, sizeof (ty));
386 return ty;
387}
388
398inline
400{
401 int err = 0;
402 getopt (SO_ERROR, &err, sizeof (err));
403 return err;
404}
405
407inline
408bool sock::debug () const
409{
410 BOOL old;
411 getopt (SO_DEBUG, &old, sizeof (old));
412 return (old != 0);
413}
414
416inline
417void sock::debug (bool b) const
418{
419 BOOL opt = b;
420 setopt (SO_DEBUG, &opt, sizeof (opt));
421}
422
424inline
425bool sock::reuseaddr () const
426{
427 BOOL old;
428 getopt (SO_REUSEADDR, &old, sizeof (old));
429 return (old != 0);
430}
431
433inline
434void sock::reuseaddr (bool b) const
435{
436 BOOL opt = b;
437 setopt (SO_REUSEADDR, &opt, sizeof (opt));
438}
439
441inline
442bool sock::keepalive () const
443{
444 BOOL old;
445 getopt (SO_KEEPALIVE, &old, sizeof (old));
446 return (old != 0);
447}
448
450inline
451void sock::keepalive (bool b) const
452{
453 BOOL opt = b;
454 setopt (SO_KEEPALIVE, &opt, sizeof (opt));
455}
456
458inline
459bool sock::dontroute () const
460{
461 BOOL old;
462 getopt (SO_DONTROUTE, &old, sizeof (old));
463 return (old != 0);
464}
465
467inline
468void sock::dontroute (bool b) const
469{
470 BOOL opt = b;
471 setopt (SO_DONTROUTE, &opt, sizeof (opt));
472}
473
475inline
476bool sock::broadcast () const
477{
478 BOOL old;
479 getopt (SO_BROADCAST, &old, sizeof (old));
480 return (old != 0);
481}
482
489inline
490void sock::broadcast (bool b) const
491{
492 BOOL opt = b;
493 setopt (SO_BROADCAST, &opt, sizeof (opt));
494}
495
500inline
501bool sock::oobinline () const
502{
503 BOOL old;
504 getopt (SO_OOBINLINE, &old, sizeof (old));
505 return (old != 0);
506}
507
512inline
513void sock::oobinline (bool b) const
514{
515 BOOL opt = b;
516 setopt (SO_OOBINLINE, &opt, sizeof (opt));
517}
518
520inline
521int sock::sendbufsz () const
522{
523 int old = 0;
524 getopt (SO_SNDBUF, &old, sizeof (old));
525 return old;
526}
527
529inline
530void sock::sendbufsz (size_t sz) const
531{
532 setopt (SO_SNDBUF, &sz, sizeof (sz));
533}
534
536inline
537int sock::recvbufsz () const
538{
539 int old = 0;
540 getopt (SO_RCVBUF, &old, sizeof (old));
541 return old;
542}
543
545inline
546void sock::recvbufsz (size_t sz) const
547{
548 setopt (SO_RCVBUF, &sz, sizeof (sz));
549}
550
556inline
557void sock::blocking (bool on_off)
558{
559 if (!sl || sl->handle == INVALID_SOCKET)
560 throw erc (WSAENOTSOCK, Errors());
561
562 unsigned long mode = on_off ? 0 : 1;
563 if (ioctlsocket (sl->handle, FIONBIO, &mode) == SOCKET_ERROR)
564 last_error ().raise ();
565}
566
567#ifdef _WIN32
583inline
584erc sock::setevent (HANDLE evt, long mask) const
585{
586 if (!sl || sl->handle == INVALID_SOCKET)
587 return erc (WSAENOTSOCK, Errors());
588
589 if (WSAEventSelect (sl->handle, (WSAEVENT)evt, mask) == SOCKET_ERROR)
590 return last_error ();
591 return erc::success;
592}
593
600inline
601long sock::enumevents () const
602{
603 if (!sl || sl->handle == INVALID_SOCKET)
604 throw erc (WSAENOTSOCK, Errors());
605
606 WSANETWORKEVENTS netev;
607 if (WSAEnumNetworkEvents (sl->handle, NULL, &netev) == SOCKET_ERROR)
608 last_error ().raise ();
609 return netev.lNetworkEvents;
610}
611#endif
612
614inline
615void sock::linger (bool on_off, unsigned short seconds) const
616{
617 struct linger opt;
618 opt.l_onoff = on_off;
619 opt.l_linger = seconds;
620 setopt (SO_LINGER, &opt, sizeof (opt));
621}
622
624inline
625bool sock::linger (unsigned short* seconds) const
626{
627 struct linger opt;
628 getopt (SO_LINGER, &opt, sizeof (opt));
629 if (seconds)
630 *seconds = opt.l_linger;
631 return (opt.l_onoff == 0);
632}
633
635inline
636void sock::nodelay (bool on_off)
637{
638 int value = on_off;
639 setopt (TCP_NODELAY, &value, sizeof (int), IPPROTO_TCP);
640}
641
643inline
644bool sock::nodelay () const
645{
646 int value;
647 getopt (TCP_NODELAY, &value, sizeof (int), IPPROTO_TCP);
648 return (value != 0);
649}
650
652inline
654{
655#ifdef _WIN32
656 int code = WSAGetLastError ();
657#else
658 int code = errno;
659#endif
660 if (!code)
661 return erc::success;
662 else
663 return erc (code, Errors());
664}
665
672inline
673bool sock::operator== (const sock& other) const
674{
675 return (sl == other.sl);
676}
677
683inline
684bool sock::operator!= (const sock& other) const
685{
686 return !operator== (other);
687}
688
690inline
692{
693 return (sock::mflags) ((int)f1 | (int)f2);
694}
695
696} // namespace mlib
697
699inline
700std::ostream& operator<< (std::ostream& strm, const mlib::sock& s)
701{
702 strm << s.handle ();
703 return strm;
704}
705
objects returned as a function result or thrown directly.
Definition errorcode.h:73
static erc success
The SUCCESS indicator.
Definition errorcode.h:121
void raise() const
Definition errorcode.h:603
We keep a reference counter associated with each sock object because it is more expensive to duplicat...
Definition sock.h:19
bool broadcast() const
Return "broadcast" option.
Definition sock.h:476
bool reuseaddr() const
Return the "reuse address" flag.
Definition sock.h:425
bool dontroute() const
Return status of "don't route" flag.
Definition sock.h:459
checked< inaddr > peer() const
Retrieves the name of the peer to which the socket is connected.
Definition sock.cpp:244
mflags
Flags for send/receive operations.
Definition sock.h:39
@ dont_route
data should not be routed
Definition sock.h:43
@ peek
don't remove data from the input queue
Definition sock.h:42
@ none
no flags
Definition sock.h:40
@ out_of_band
send out of band data
Definition sock.h:41
@ wait_all
wait until buffer full or connection closed
Definition sock.h:44
int clearerror() const
Return and clear the socket error flag.
Definition sock.h:399
erc listen(int num=SOMAXCONN) const
Places the socket in a state in which it is listening for incoming connections.
Definition sock.h:226
void linger(bool on_off, unsigned short seconds) const
Turn on or off linger mode and lingering timeout.
Definition sock.h:615
erc bind() const
Associates a local address with the socket.
Definition sock.cpp:275
bool operator==(const sock &other) const
Equality comparison operator.
Definition sock.h:673
bool is_writeready(std::chrono::milliseconds tmo=std::chrono::milliseconds{0}) const
Check if socket is "writable".
Definition sock.cpp:519
erc setopt(int op, void *buf, int len, int level=SOL_SOCKET) const
Set a socket option.
Definition sock.h:367
int recvbufsz() const
Return buffer size for receive operations.
Definition sock.h:537
checked< inaddr > name() const
Return the local name for the object.
Definition sock.cpp:229
virtual bool is_open() const
Check if socket is opened.
Definition sock.h:183
erc connect(const inaddr &peer) const
Establishes a connection to specified peer.
Definition sock.h:190
int getopt(int op, void *buf, int len, int level=SOL_SOCKET) const
Returns a socket option.
Definition sock.h:348
void blocking(bool on_off)
Change blocking mode.
Definition sock.h:557
size_t sendto(const sockaddr &sa, const void *buf, size_t len, mflags msgf=mflags::none) const
Send data to a peer.
Definition sock.cpp:452
int gettype() const
Return socket type (SOCK_DGRAM or SOCK_STREAM)
Definition sock.h:382
std::chrono::milliseconds sendtimeout() const
Returns the send timeout value.
Definition sock.h:285
bool debug() const
Return the debug flag.
Definition sock.h:408
bool is_readready(std::chrono::milliseconds tmo=std::chrono::milliseconds{0}) const
Check if socket is "readable".
Definition sock.cpp:490
bool oobinline() const
Return the status of the OOB_INLINE flag.
Definition sock.h:501
unsigned int nread() const
Return number of characters waiting in socket's buffer.
Definition sock.cpp:563
size_t recv(void *buf, size_t maxlen, mflags msgf=mflags::none) const
Receives data from socket.
Definition sock.cpp:352
sock()
Default constructor creates a closed socket.
Definition sock.h:163
size_t send(const void *buf, size_t len, mflags msgf=mflags::none) const
Send data to the connected peer.
Definition sock.cpp:416
bool operator!=(const sock &other) const
Inequality comparison operator.
Definition sock.h:684
type
socket types
Definition sock.h:23
shuthow
operation blocked by shutdown function
Definition sock.h:31
@ shut_readwrite
blocked for both
Definition sock.h:34
@ shut_read
blocked for reading
Definition sock.h:32
@ shut_write
blocked for writing
Definition sock.h:33
size_t recvfrom(sockaddr &sa, void *buf, size_t maxlen, mflags msgf=mflags::none) const
Receives data from socket.
Definition sock.cpp:384
bool connected() const
Check is socket is connected.
Definition sock.h:204
virtual erc shutdown(shuthow sh) const
Disables sends or receives on socket.
Definition sock.cpp:579
int sendbufsz() const
Return buffer size for send operations.
Definition sock.h:521
HANDLE handle() const
Retrieve Windows socket handle.
Definition sock.h:169
static errfac & Errors()
Return error facility used by all sock-derived classes.
Definition sock.cpp:36
erc accept(sock &client, inaddr *sa=nullptr) const
Permits an incoming connection attempt on the socket.
Definition sock.h:211
virtual ~sock()
Destructor.
Definition sock.cpp:162
bool is_exceptionpending(std::chrono::milliseconds tmo=std::chrono::milliseconds{0}) const
Check if socket has OOB data or any exceptional error conditions.
Definition sock.cpp:542
static erc last_error()
Return an error code with the value returned by WSAGetLastError.
Definition sock.h:653
bool keepalive() const
Return "keep alive" flag.
Definition sock.h:442
virtual void close()
Close socket.
Definition sock.cpp:200
virtual erc open(type t, int domain=AF_INET, int proto=0)
Open the socket.
Definition sock.cpp:185
std::chrono::milliseconds recvtimeout() const
Returns the send timeout value.
Definition sock.h:322
bool nodelay() const
Return status of TCP_NODELAY option.
Definition sock.h:644
sock & operator=(const sock &)
Assignment operator.
Definition sock.cpp:129
@ seconds
Degrees, minutes, seconds format (DD°MM'SS.sss")
Definition convert.h:249
Definition of mlib::erc and mlib::errfac classes.
sock::mflags operator|(sock::mflags f1, sock::mflags f2)
Bitwise OR operator for send message flags.
Definition sock.h:691
std::chrono::microseconds to_chrono(const timeval &tv)
Conversion to a chrono duration in microseconds.
Definition tvops.h:200
timeval from_chrono(const T &dur)
Conversion from a chrono duration.
Definition tvops.h:190
Definition of mlib::inaddr class.
Operations on timeval structure.