VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gsocket.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
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_SOCKET_H
22 #define G_SOCKET_H
23 
24 #include "gdef.h"
25 #include "gnet.h"
26 #include "gaddress.h"
27 #include "gexception.h"
28 #include "gevent.h"
29 #include "gdescriptor.h"
30 #include "greadwrite.h"
31 #include <string>
32 
33 namespace GNet
34 {
35  class Socket ;
36  class SocketProtocol ;
37  class StreamSocket ;
38  class DatagramSocket ;
39  class AcceptPair ;
40 }
41 
42 /// \class GNet::Socket
43 ///
44 /// The Socket class encapsulates a non-blocking Unix socket file descriptor or a
45 /// Windows 'SOCKET' handle.
46 ///
47 /// (Non-blocking network i/o is particularly appropriate for single-threaded
48 /// server processes which manage multiple client connections. The main
49 /// disagvantage is that flow control has to be managed explicitly: see
50 /// Socket::write() and Socket::eWouldBlock().)
51 ///
52 /// Provides bind(), listen(), connect(), write(); derived classes provide
53 /// accept() and read(). Also interfaces to the event loop with addReadHandler()
54 /// and addWriteHandler().
55 ///
56 class GNet::Socket : public G::ReadWrite
57 {
58 public:
59  G_EXCEPTION( SocketError , "socket error" ) ;
60  G_EXCEPTION( SocketBindError , "socket bind error" ) ;
61  typedef G::ReadWrite::size_type size_type ;
62  typedef G::ReadWrite::ssize_type ssize_type ;
63  struct NoThrow /// Overload discriminator class for GNet::Socket.
64  {} ;
65 
66  virtual ~Socket() ;
67  ///< Destructor.
68 
69  std::pair<bool,Address> getLocalAddress() const ;
70  ///< Retrieves local address of the socket.
71  ///< Pair.first is false on error.
72 
73  std::pair<bool,Address> getPeerAddress() const ;
74  ///< Retrieves address of socket's peer.
75  ///< 'Pair.first' is false on error.
76 
77  bool hasPeer() const ;
78  ///< Returns true if the socket has a valid peer. This
79  ///< can be used to see if a connect succeeded.
80 
81  void bind( const Address & ) ;
82  ///< Binds the socket with the given address.
83 
84  bool bind( const Address & , NoThrow ) ;
85  ///< No-throw overload. Returns false on error.
86 
87  bool canBindHint( const Address & address ) ;
88  ///< Returns true if the socket can probably be bound
89  ///< with the given address. Some implementations will
90  ///< always return true. This method should be used on
91  ///< a temporary socket of the correct dynamic type
92  ///< since this socket may become unusable.
93 
94  bool connect( const Address & addr , bool *done = nullptr ) ;
95  ///< Initiates a connection to (or association with)
96  ///< the given address. Returns false on error.
97  ///<
98  ///< If successful, a 'done' flag is returned by
99  ///< reference indicating whether the connect completed
100  ///< immediately. Normally a stream socket connection
101  ///< will take some time to complete so the 'done' flag
102  ///< will be false: the completion will be indicated by
103  ///< a write event some time later.
104  ///<
105  ///< For datagram sockets this sets up an association
106  ///< between two addresses. The socket should first be
107  ///< bound with a local address.
108 
109  void listen( int backlog = 1 ) ;
110  ///< Starts the socket listening on the bound
111  ///< address for incoming connections or incoming
112  ///< datagrams.
113 
114  virtual ssize_type read( char * buffer , size_type buffer_length ) override = 0 ;
115  ///< Reads from the socket. This is a default implementation
116  ///< that can be called explicitly from derived classes.
117 
118  virtual ssize_type write( const char * buf , size_type len ) override = 0 ;
119  ///< Writes to the socket. This is a default implementation
120  ///< that can be called explicitly from derived classes.
121  ///< Override from G::ReadWrite.
122 
123  virtual SOCKET fd() const ;
124  ///< Returns the socket descriptor. Override from G::ReadWrite.
125 
126  virtual bool eWouldBlock() ;
127  ///< Returns true if the previous socket operation
128  ///< failed because the socket would have blocked.
129  ///< Override from G::ReadWrite.
130 
131  bool eInProgress() ;
132  ///< Returns true if the previous socket operation
133  ///< failed with the EINPROGRESS error status.
134  ///< When connecting this can be considered a
135  ///< non-error.
136 
137  bool eMsgSize() ;
138  ///< Returns true if the previous socket operation
139  ///< failed with the EMSGSIZE error status. When
140  ///< writing to a datagram socket this indicates that
141  ///< the message was too big to send atomically.
142 
143  void addReadHandler( EventHandler & handler ) ;
144  ///< Adds this socket to the event source list so that
145  ///< the given handler receives read events.
146 
147  void dropReadHandler();
148  ///< Reverses addReadHandler().
149 
150  void addWriteHandler( EventHandler & handler ) ;
151  ///< Adds this socket to the event source list so that
152  ///< the given handler receives write events when flow
153  ///< control is released. (Not used for datagram
154  ///< sockets.)
155 
156  void dropWriteHandler() ;
157  ///< Reverses addWriteHandler().
158 
159  void addExceptionHandler( EventHandler & handler );
160  ///< Adds this socket to the event source list so that
161  ///< the given handler receives exception events.
162  ///< A TCP exception event should be treated as a
163  ///< disconnection event. (Not used for datagram
164  ///< sockets.)
165 
166  void dropExceptionHandler() ;
167  ///< Reverses addExceptionHandler().
168 
169  std::string asString() const ;
170  ///< Returns the socket handle as a string.
171  ///< Only used in debugging.
172 
173  std::string reasonString() const ;
174  ///< Returns the failure reason as a string.
175  ///< Only used in debugging.
176 
177  void shutdown( bool for_writing = true ) ;
178  ///< Shuts the socket for writing (or reading).
179 
180 protected:
181  Socket( int domain , int type , int protocol ) ;
182  ///< Constructor used by derived classes. Opens the
183  ///< socket using socket().
184 
185  explicit Socket( Descriptor s ) ;
186  ///< Constructor which creates a socket object from
187  ///< an existing socket handle. Used only by
188  ///< StreamSocket::accept().
189 
190 protected:
191  static int reason() ;
192  static std::string reasonStringImp( int ) ;
193  static bool error( int rc ) ;
194  static bool sizeError( ssize_type size ) ;
195  void saveReason() ;
196  void saveReason() const ;
197  void prepare() ;
198  void setFault() ;
199  void setOptionNoLinger() ;
200  void setOptionReuse() ;
201  void setOptionExclusive() ;
202  void setOptionPureV6( bool ) ;
203  bool setOptionPureV6( bool , NoThrow ) ;
204  void setOptionKeepAlive() ;
205  void setOption( int , const char * , int , int ) ;
206  bool setOption( int , const char * , int , int , NoThrow ) ;
207  bool setOptionImp( int , int , const void * , socklen_t ) ;
208  std::pair<bool,Address> getAddress( bool ) const ;
209 
210 private:
211  void doClose() ;
212  bool setNonBlock() ;
213 
214 protected:
215  int m_reason ;
216  std::string m_reason_string ;
217  int m_domain ;
218  Descriptor m_socket ;
219 
220 private:
221  Socket( const Socket & ) ;
222  void operator=( const Socket & ) ;
223  void drop() ;
224 } ;
225 
226 //
227 
228 /// \class GNet::AcceptPair
229 /// A class which is used to return a new()ed socket to calling code, together
230 /// with associated information.
231 ///
233 {
234 public:
235  shared_ptr<StreamSocket> first ;
236  Address second ;
237  AcceptPair() : second(Address::defaultAddress()) {}
238 } ;
239 
240 //
241 
242 /// \class GNet::StreamSocket
243 /// A derivation of GNet::Socket for a stream socket.
244 ///
246 {
247 public:
248  typedef Socket::size_type size_type ;
249  typedef Socket::ssize_type ssize_type ;
250 
251  explicit StreamSocket( int address_domain ) ;
252  ///< Constructor with a hint of the bind()/connect()
253  ///< address to be used later.
254 
255  virtual ~StreamSocket() ;
256  ///< Destructor.
257 
258  virtual ssize_type read( char * buffer , size_type buffer_length ) ;
259  ///< Override from Socket::read().
260 
261  virtual ssize_type write( const char * buf , size_type len ) ;
262  ///< Override from Socket::write().
263 
264  AcceptPair accept() ;
265  ///< Accepts an incoming connection, returning
266  ///< a new()ed socket and the peer address.
267 
268 private:
269  StreamSocket( const StreamSocket & ) ; // not implemented
270  void operator=( const StreamSocket & ) ; // not implemented
271  StreamSocket( Descriptor s ) ; // A private constructor used in accept().
272 } ;
273 
274 //
275 
276 /// \class GNet::DatagramSocket
277 /// A derivation of GNet::Socket for a datagram socket.
278 ///
280 {
281 public:
282  explicit DatagramSocket( int address_domain ) ;
283  ///< Constructor with a hint of a local address.
284 
285  virtual ~DatagramSocket() ;
286  ///< Destructor.
287 
288  virtual ssize_type read( char * buffer , size_type len ) ;
289  ///< Override from Socket::read().
290 
291  virtual ssize_type write( const char * buffer , size_type len ) ;
292  ///< Override from Socket::write().
293 
294  ssize_type readfrom( char * buffer , size_type len , Address & src ) ;
295  ///< Reads a datagram and returns the sender's address by reference.
296  ///< If connect() has been used then only datagrams from the address
297  ///< specified in the connect() call will be received.
298 
299  ssize_type writeto( const char * buffer , size_type len , const Address & dst ) ;
300  ///< Sends a datagram to the given address. This should be used
301  ///< if there is no connect() assocation in effect.
302 
303  void disconnect() ;
304  ///< Releases the association between two datagram endpoints
305  ///< reversing the effect of the previous Socket::connect().
306 
307 private:
308  DatagramSocket( const DatagramSocket & ) ; // not implemented
309  void operator=( const DatagramSocket & ) ; // not implemented
310 } ;
311 
312 #endif
bool canBindHint(const Address &address)
Returns true if the socket can probably be bound with the given address.
virtual ssize_type read(char *buffer, size_type len)
Override from Socket::read().
Definition: gsocket.cpp:357
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:49
std::pair< bool, Address > getLocalAddress() const
Retrieves local address of the socket.
Definition: gsocket.cpp:207
void listen(int backlog=1)
Starts the socket listening on the bound address for incoming connections or incoming datagrams...
Definition: gsocket.cpp:179
bool connect(const Address &addr, bool *done=nullptr)
Initiates a connection to (or association with) the given address.
Definition: gsocket.cpp:125
void dropReadHandler()
Reverses addReadHandler().
Definition: gsocket.cpp:228
void addExceptionHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives exception events...
Definition: gsocket.cpp:239
virtual bool eWouldBlock()
Returns true if the previous socket operation failed because the socket would have blocked...
void addWriteHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives write events when flow c...
Definition: gsocket.cpp:233
virtual ~DatagramSocket()
Destructor.
Definition: gsocket.cpp:346
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:55
The Socket class encapsulates a non-blocking Unix socket file descriptor or a Windows 'SOCKET' handle...
Definition: gsocket.h:56
A derivation of GNet::Socket for a datagram socket.
Definition: gsocket.h:279
void addReadHandler(EventHandler &handler)
Adds this socket to the event source list so that the given handler receives read events...
Definition: gsocket.cpp:222
StreamSocket(int address_domain)
Constructor with a hint of the bind()/connect() address to be used later.
Definition: gsocket.cpp:281
virtual SOCKET fd() const
Returns the socket descriptor. Override from G::ReadWrite.
Definition: gsocket.cpp:274
virtual ~StreamSocket()
Destructor.
Definition: gsocket.cpp:293
A class that encapsulates a network file descriptor and hides knowledge of its o/s-spefific error val...
Definition: gdescriptor.h:37
ssize_type writeto(const char *buffer, size_type len, const Address &dst)
Sends a datagram to the given address.
Definition: gsocket.cpp:386
DatagramSocket(int address_domain)
Constructor with a hint of a local address.
Definition: gsocket.cpp:341
void dropExceptionHandler()
Reverses addExceptionHandler().
Definition: gsocket.cpp:250
bool eMsgSize()
Returns true if the previous socket operation failed with the EMSGSIZE error status.
void dropWriteHandler()
Reverses addWriteHandler().
Definition: gsocket.cpp:245
void bind(const Address &)
Binds the socket with the given address.
Definition: gsocket.cpp:93
std::string reasonString() const
Returns the failure reason as a string.
Definition: gsocket.cpp:262
void disconnect()
Releases the association between two datagram endpoints reversing the effect of the previous Socket::...
Definition: gsocket.cpp:350
std::pair< bool, Address > getPeerAddress() const
Retrieves address of socket's peer.
Definition: gsocket.cpp:212
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:245
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
virtual ~Socket()
Destructor.
Definition: gsocket.cpp:63
Socket(int domain, int type, int protocol)
Constructor used by derived classes.
Definition: gsocket.cpp:32
A class which is used to return a new()ed socket to calling code, together with associated informatio...
Definition: gsocket.h:232
A base class for classes that handle asynchronous events from the event loop.
Definition: geventhandler.h:78
virtual ssize_type write(const char *buf, size_type len) override=0
Writes to the socket.
Definition: gsocket.cpp:160
bool eInProgress()
Returns true if the previous socket operation failed with the EINPROGRESS error status.
bool hasPeer() const
Returns true if the socket has a valid peer.
Definition: gsocket.cpp:217
virtual ssize_type read(char *buffer, size_type buffer_length)
Override from Socket::read().
Definition: gsocket.cpp:297
virtual ssize_type read(char *buffer, size_type buffer_length) override=0
Reads from the socket.
virtual ssize_type write(const char *buf, size_type len)
Override from Socket::write().
Definition: gsocket.cpp:312
void shutdown(bool for_writing=true)
Shuts the socket for writing (or reading).
Definition: gsocket.cpp:269
AcceptPair accept()
Accepts an incoming connection, returning a new()ed socket and the peer address.
Definition: gsocket.cpp:317
Overload discriminator class for GNet::Socket.
Definition: gsocket.h:63
virtual ssize_type write(const char *buffer, size_type len)
Override from Socket::write().
Definition: gsocket.cpp:400
ssize_type readfrom(char *buffer, size_type len, Address &src)
Reads a datagram and returns the sender's address by reference.
Definition: gsocket.cpp:371
std::string asString() const
Returns the socket handle as a string.
Definition: gsocket.cpp:255