E-MailRelay

gsocket.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gsocket.h
19///
20
21#ifndef G_NET_SOCKET_H
22#define G_NET_SOCKET_H
23
24#include "gdef.h"
25#include "gaddress.h"
26#include "gexceptionsink.h"
27#include "gexception.h"
28#include "gevent.h"
29#include "gdescriptor.h"
30#include "greadwrite.h"
31#include "gstringview.h"
32#include <string>
33#include <memory>
34#include <new>
35
36 namespace GNet
37{
38 class SocketBase ;
39 class Socket ;
40 class SocketProtocol ;
41 class StreamSocket ;
42 class DatagramSocket ;
43 class RawSocket ;
44 class AcceptPair ;
45}
46
47//| \class GNet::SocketBase
48/// A socket base class that holds a non-blocking socket file descriptor and
49/// interfaces to the event loop.
50///
51 class GNet::SocketBase : public G::ReadWrite
52{
53 public:
54 G_EXCEPTION( SocketError , "socket error" ) ;
55 G_EXCEPTION_CLASS( SocketCreateError , "socket create error" ) ;
56 G_EXCEPTION_CLASS( SocketBindError , "socket bind error" ) ;
57 G_EXCEPTION_CLASS( SocketTooMany , "socket accept error" ) ;
58 using size_type = G::ReadWrite::size_type ;
59 using ssize_type = G::ReadWrite::ssize_type ;
60 struct Accepted /// Overload discriminator class for GNet::SocketBase.
61 {} ;
62 struct Raw /// Overload discriminator class for GNet::SocketBase.
63 {} ;
64
65 static bool supports( Address::Family , int type , int protocol ) ;
66 ///< Returns true if sockets can be created with the
67 ///< given parameters.
68
69 ~SocketBase() override ;
70 ///< Destructor. The socket file descriptor is closed and
71 ///< removed from the event loop.
72
73 SOCKET fd() const noexcept override ;
74 ///< Returns the socket file descriptor.
75
76 bool eWouldBlock() const override ;
77 ///< Returns true if the previous socket operation
78 ///< failed because the socket would have blocked.
79
80 bool eInProgress() const ;
81 ///< Returns true if the previous socket operation
82 ///< failed with the EINPROGRESS error status.
83 ///< When connecting this can be considered a
84 ///< non-error.
85
86 bool eMsgSize() const ;
87 ///< Returns true if the previous socket operation
88 ///< failed with the EMSGSIZE error status. When
89 ///< writing to a datagram socket this indicates that
90 ///< the message was too big to send atomically.
91
92 bool eTooMany() const ;
93 ///< Returns true if the previous socket operation
94 ///< failed with the EMFILE error status, or similar.
95
96 bool eNotConn() const ;
97 ///< Returns true if the previous socket operation
98 ///< failed with the ENOTCONN error status, or similar.
99
100 void addReadHandler( EventHandler & , ExceptionSink ) ;
101 ///< Adds this socket to the event source list so that
102 ///< the given handler receives read events.
103
104 void dropReadHandler() noexcept ;
105 ///< Reverses addReadHandler().
106
107 void addWriteHandler( EventHandler & , ExceptionSink ) ;
108 ///< Adds this socket to the event source list so that
109 ///< the given handler receives write events when flow
110 ///< control is released. (Not used for datagram
111 ///< sockets.)
112
113 void dropWriteHandler() noexcept ;
114 ///< Reverses addWriteHandler().
115
116 void addOtherHandler( EventHandler & , ExceptionSink ) ;
117 ///< Adds this socket to the event source list so that
118 ///< the given handler receives exception events.
119 ///< A TCP exception event should be treated as a
120 ///< disconnection event. (Not used for datagram
121 ///< sockets.)
122
123 void dropOtherHandler() noexcept ;
124 ///< Reverses addOtherHandler().
125
126 std::string asString() const ;
127 ///< Returns the socket handle as a string.
128 ///< Only used in debugging.
129
130 std::string reason() const ;
131 ///< Returns the reason for the previous error.
132
133protected:
134 SocketBase( Address::Family , int type , int protocol ) ;
135 ///< Constructor used by derived classes. Creates the
136 ///< socket using socket() and makes it non-blocking.
137
138 SocketBase( Address::Family , Descriptor s ) ;
139 ///< Constructor used by derived classes. Creates the
140 ///< socket object from a newly-created socket handle
141 ///< and makes it non-blocking.
142
143 SocketBase( Address::Family , Descriptor s , const Accepted & ) ;
144 ///< Constructor used by StreamSocket::accept() to create
145 ///< a socket object from a newly accept()ed socket
146 ///< handle.
147
148 SocketBase( const Raw & , int domain , int type , int protocol ) ;
149 ///< Constructor for a raw socket.
150
151 ssize_type writeImp( const char * buf , size_type len ) ;
152 ///< Writes to the socket. This is a default implementation
153 ///< for write() that can be called from derived classes'
154 ///< overrides.
155
156 static bool error( int rc ) ;
157 ///< Returns true if the given return code indicates an
158 ///< error.
159
160 static bool sizeError( ssize_type size ) ;
161 ///< Returns true if the given write() return value
162 ///< indicates an error.
163
164 void clearReason() ;
165 ///< Clears the saved errno.
166
167 void saveReason() ;
168 ///< Saves the current errno following error()/sizeError().
169
170 void saveReason() const ;
171 ///< Saves the current errno following error()/sizeError().
172
173 bool isFamily( Address::Family ) const ;
174 ///< Returns true if the socket family is as given.
175
176private:
177 static std::string reasonString( int ) ;
178 bool create( int , int , int ) ;
179 bool prepare( bool ) ;
180 void drop() noexcept ;
181 void destroy() noexcept ;
182 void unlink() noexcept ;
183 bool setNonBlocking() ;
184
185public:
186 SocketBase( const SocketBase & ) = delete ;
187 SocketBase( SocketBase && ) = delete ;
188 void operator=( const SocketBase & ) = delete ;
189 void operator=( SocketBase && ) = delete ;
190
191private:
192 int m_reason ;
193 int m_domain ;
194 Address::Family m_family ; // valid depending on m_domain
195 Descriptor m_fd ;
196 bool m_added ;
197 bool m_accepted ;
198} ;
199
200//| \class GNet::Socket
201/// An internet-protocol socket class. Provides bind(), listen(),
202/// and connect(); the base classes provide write(); and derived
203/// classes provide accept() and read().
204///
205 class GNet::Socket : public SocketBase
206{
207 public:
208 Address getLocalAddress() const ;
209 ///< Retrieves local address of the socket.
210
211 std::pair<bool,Address> getPeerAddress() const ;
212 ///< Retrieves address of socket's peer.
213 ///< Returns false in 'first' if none, ie. not yet
214 ///< connected.
215
216 void bind( const Address & ) ;
217 ///< Binds the socket with the given address.
218
219 bool bind( const Address & , std::nothrow_t ) ;
220 ///< No-throw overload. Returns false on error.
221
222 static std::string canBindHint( const Address & address , bool stream_socket = true ) ;
223 ///< Returns the empty string if a socket could probably be
224 ///< bound with the given address or a failure reason.
225 ///< Some implementations will always return the empty
226 ///< string.
227
228 unsigned long getBoundScopeId() const ;
229 ///< Returns the scope-id of the address last successfully
230 ///< bind()ed. Note that getLocalAddress() has a zero
231 ///< scope-id even after bind()ing an address with
232 ///< a non-zero scope-id.
233
234 bool connect( const Address & addr , bool *done = nullptr ) ;
235 ///< Initiates a connection to (or association with)
236 ///< the given address. Returns false on error.
237 ///<
238 ///< If successful, a 'done' flag is returned by
239 ///< reference indicating whether the connect completed
240 ///< immediately. Normally a stream socket connection
241 ///< will take some time to complete so the 'done' flag
242 ///< will be false: the completion will be indicated by
243 ///< a write event some time later.
244 ///<
245 ///< For datagram sockets this sets up an association
246 ///< between two addresses. The socket should first be
247 ///< bound with a local address.
248
249 void listen( int backlog = 1 ) ;
250 ///< Starts the socket listening on the bound
251 ///< address for incoming connections or incoming
252 ///< datagrams.
253
254 void shutdown( int how = 1 ) ;
255 ///< Modifies the local socket state so that so that new
256 ///< sends (1 or 2) and/or receives (0 or 2) will fail.
257 ///<
258 ///< If receives are shut-down then anything received
259 ///< will be rejected with a RST.
260 ///<
261 ///< If sends are shut-down then the transmit queue is
262 ///< drained and a final empty FIN packet is sent when
263 ///< fully acknowledged. See also RFC-793 3.5.
264 ///<
265 ///< Errors are ignored.
266
267 public:
268 ~Socket() override = default ;
269 Socket( const Socket & ) = delete ;
270 Socket( Socket && ) = delete ;
271 void operator=( const Socket & ) = delete ;
272 void operator=( Socket && ) = delete ;
273
274 protected:
275 Socket( Address::Family , int type , int protocol ) ;
276 Socket( Address::Family , Descriptor s , const Accepted & ) ;
277 std::pair<bool,Address> getLocalAddress( std::nothrow_t ) const ;
278 void setOption( int , const char * , int , int ) ;
279 bool setOption( int , const char * , int , int , std::nothrow_t ) ;
280 bool setOptionImp( int , int , const void * , socklen_t ) ;
281 void setOptionsOnBind( Address::Family ) ;
282 void setOptionsOnConnect( Address::Family ) ;
283 void setOptionLingerImp( int , int ) ;
284 void setOptionNoLinger() ;
285 void setOptionReuse() ;
286 void setOptionExclusive() ;
287 void setOptionPureV6() ;
288 bool setOptionPureV6( std::nothrow_t ) ;
289 void setOptionKeepAlive() ;
290
291 private:
292 unsigned long m_bound_scope_id{0UL} ;
293} ;
294
295//| \class GNet::AcceptPair
296/// A class which is used to return a new()ed socket to calling
297/// code, together with associated address information.
298///
299 class GNet::AcceptPair
300{
301 public:
302 std::shared_ptr<StreamSocket> socket_ptr ;
303 Address address ;
304 AcceptPair() : address(Address::defaultAddress()) {}
305} ;
306
307//| \class GNet::StreamSocket
308/// A derivation of GNet::Socket for a stream socket.
309///
310 class GNet::StreamSocket : public Socket
311{
312 public:
313 using size_type = Socket::size_type ;
314 using ssize_type = Socket::ssize_type ;
315 struct Listener /// Overload discriminator class for GNet::StreamSocket.
316 {} ;
317
318 static bool supports( Address::Family ) ;
319 ///< Returns true if stream sockets can be created with the
320 ///< given the address family. This is a one-off run-time
321 ///< check on socket creation, with a warning if it fails.
322 ///< Note that a run-time check is useful when running a
323 ///< new binary on an old operating system.
324
325 explicit StreamSocket( Address::Family ) ;
326 ///< Constructor.
327
328 StreamSocket( Address::Family , const Listener & ) ;
329 ///< Constructor overload specifically for a listening
330 ///< socket, which might need slightly different socket
331 ///< options.
332
333 ssize_type read( char * buffer , size_type buffer_length ) override ;
334 ///< Override from ReadWrite::read().
335
336 ssize_type write( const char * buf , size_type len ) override ;
337 ///< Override from Socket::write().
338
339 AcceptPair accept() ;
340 ///< Accepts an incoming connection, returning a new()ed
341 ///< socket and the peer address.
342
343 public:
344 ~StreamSocket() override = default ;
345 StreamSocket( const StreamSocket & ) = delete ;
346 StreamSocket( StreamSocket && ) = delete ;
347 void operator=( const StreamSocket & ) = delete ;
348 void operator=( StreamSocket && ) = delete ;
349
350 private:
351 StreamSocket( Address::Family , Descriptor s , const Accepted & ) ;
352 void setOptionsOnCreate( Address::Family , bool listener ) ;
353 void setOptionsOnAccept( Address::Family ) ;
354} ;
355
356//| \class GNet::DatagramSocket
357/// A derivation of GNet::Socket for a datagram socket.
358///
359 class GNet::DatagramSocket : public Socket
360{
361 public:
362 explicit DatagramSocket( Address::Family , int protocol = 0 ) ;
363 ///< Constructor.
364
365 ssize_type read( char * buffer , size_type len ) override ;
366 ///< Override from ReadWrite::read().
367
368 ssize_type write( const char * buffer , size_type len ) override ;
369 ///< Override from Socket::write().
370
371 ssize_type readfrom( char * buffer , size_type len , Address & src ) ;
372 ///< Reads a datagram and returns the sender's address by reference.
373 ///< If connect() has been used then only datagrams from the address
374 ///< specified in the connect() call will be received.
375
376 ssize_type writeto( const char * buffer , size_type len , const Address & dst ) ;
377 ///< Sends a datagram to the given address. This should be used
378 ///< if there is no connect() assocation in effect.
379
380 void disconnect() ;
381 ///< Releases the association between two datagram endpoints
382 ///< reversing the effect of the previous Socket::connect().
383
384 public:
385 ~DatagramSocket() override = default ;
386 DatagramSocket( const DatagramSocket & ) = delete ;
387 DatagramSocket( DatagramSocket && ) = delete ;
388 void operator=( const DatagramSocket & ) = delete ;
389 void operator=( DatagramSocket && ) = delete ;
390} ;
391
392//| \class GNet::RawSocket
393/// A derivation of GNet::SocketBase for a raw socket, typically of
394/// type AF_NETLINK or PF_ROUTE.
395///
396 class GNet::RawSocket : public SocketBase
397{
398 public:
399 RawSocket( int domain , int type , int protocol ) ;
400 ///< Constructor.
401
402 ssize_type read( char * buffer , size_type buffer_length ) override ;
403 ///< Reads from the socket.
404
405 ssize_type write( const char * buf , size_type len ) override ;
406 ///< Writes to the socket.
407
408 public:
409 ~RawSocket() override = default ;
410 RawSocket( const RawSocket & ) = delete ;
411 RawSocket( RawSocket && ) = delete ;
412 void operator=( const RawSocket & ) = delete ;
413 void operator=( RawSocket && ) = delete ;
414} ;
415
416#endif
GNet::AcceptPair
A class which is used to return a new()ed socket to calling code, together with associated address in...
Definition: gsocket.h:300
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:53
GNet::Address::defaultAddress
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress.cpp:242
GNet::DatagramSocket
A derivation of GNet::Socket for a datagram socket.
Definition: gsocket.h:360
GNet::Descriptor
A class that encapsulates a network socket file descriptor and an associated windows event handle.
Definition: gdescriptor.h:37
GNet::EventHandler
A base class for classes that handle asynchronous events from the event loop.
Definition: geventhandler.h:48
GNet::ExceptionSink
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
Definition: gexceptionsink.h:100
GNet::RawSocket
A derivation of GNet::SocketBase for a raw socket, typically of type AF_NETLINK or PF_ROUTE.
Definition: gsocket.h:397
GNet::SocketBase
A socket base class that holds a non-blocking socket file descriptor and interfaces to the event loop...
Definition: gsocket.h:52
GNet::SocketBase::eNotConn
bool eNotConn() const
Returns true if the previous socket operation failed with the ENOTCONN error status,...
Definition: gsocket_unix.cpp:120
GNet::SocketBase::eInProgress
bool eInProgress() const
Returns true if the previous socket operation failed with the EINPROGRESS error status.
Definition: gsocket_unix.cpp:130
GNet::SocketBase::~SocketBase
~SocketBase() override
Destructor.
Definition: gsocket.cpp:123
GNet::SocketBase::reason
std::string reason() const
Returns the reason for the previous error.
Definition: gsocket.cpp:216
GNet::SocketBase::fd
SOCKET fd() const noexcept override
Returns the socket file descriptor.
Definition: gsocket.cpp:211
GNet::SocketBase::clearReason
void clearReason()
Clears the saved errno.
Definition: gsocket.cpp:143
GNet::SocketBase::asString
std::string asString() const
Returns the socket handle as a string.
Definition: gsocket.cpp:222
GNet::SocketBase::dropReadHandler
void dropReadHandler() noexcept
Reverses addReadHandler().
Definition: gsocket.cpp:193
GNet::SocketBase::addOtherHandler
void addOtherHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives exception events.
Definition: gsocket.cpp:186
GNet::SocketBase::error
static bool error(int rc)
Returns true if the given return code indicates an error.
Definition: gsocket_unix.cpp:95
GNet::SocketBase::eMsgSize
bool eMsgSize() const
Returns true if the previous socket operation failed with the EMSGSIZE error status.
Definition: gsocket_unix.cpp:135
GNet::SocketBase::isFamily
bool isFamily(Address::Family) const
Returns true if the socket family is as given.
Definition: gsocket.cpp:129
GNet::SocketBase::addReadHandler
void addReadHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives read events.
Definition: gsocket.cpp:172
GNet::SocketBase::sizeError
static bool sizeError(ssize_type size)
Returns true if the given write() return value indicates an error.
Definition: gsocket_unix.cpp:115
GNet::SocketBase::supports
static bool supports(Address::Family, int type, int protocol)
Returns true if sockets can be created with the given parameters.
Definition: gsocket_unix.cpp:34
GNet::SocketBase::addWriteHandler
void addWriteHandler(EventHandler &, ExceptionSink)
Adds this socket to the event source list so that the given handler receives write events when flow c...
Definition: gsocket.cpp:179
GNet::SocketBase::dropOtherHandler
void dropOtherHandler() noexcept
Reverses addOtherHandler().
Definition: gsocket.cpp:205
GNet::SocketBase::writeImp
ssize_type writeImp(const char *buf, size_type len)
Writes to the socket.
Definition: gsocket.cpp:153
GNet::SocketBase::eWouldBlock
bool eWouldBlock() const override
Returns true if the previous socket operation failed because the socket would have blocked.
Definition: gsocket_unix.cpp:125
GNet::SocketBase::eTooMany
bool eTooMany() const
Returns true if the previous socket operation failed with the EMFILE error status,...
Definition: gsocket_unix.cpp:140
GNet::SocketBase::dropWriteHandler
void dropWriteHandler() noexcept
Reverses addWriteHandler().
Definition: gsocket.cpp:199
GNet::SocketBase::saveReason
void saveReason()
Saves the current errno following error()/sizeError().
Definition: gsocket_unix.cpp:100
GNet::Socket
An internet-protocol socket class.
Definition: gsocket.h:206
GNet::StreamSocket
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:311
G::ReadWrite
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:50
G::ReadWrite::write
virtual ssize_type write(const char *buf, size_type len)=0
Sends data.
G::ReadWrite::read
virtual ssize_type read(char *buffer, size_type buffer_length)=0
Reads data.
gaddress.h
gdescriptor.h
gevent.h
gexception.h
gexceptionsink.h
greadwrite.h
gstringview.h
GNet
Network classes.
Definition: gdef.h:1115
GNet::SocketBase::Accepted
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:61
GNet::SocketBase::Raw
Overload discriminator class for GNet::SocketBase.
Definition: gsocket.h:63
GNet::StreamSocket::Listener
Overload discriminator class for GNet::StreamSocket.
Definition: gsocket.h:316