E-MailRelay
gsocketprotocol.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 gsocketprotocol.h
19///
20
21#ifndef G_NET_SOCKET_PROTOCOL_H
22#define G_NET_SOCKET_PROTOCOL_H
23
24#include "gdef.h"
25#include "gsocket.h"
26#include "geventhandler.h"
27#include "gexception.h"
28#include "gstringview.h"
29#include <string>
30#include <vector>
31#include <utility>
32
33namespace GNet
34{
35 class SocketProtocol ;
36 class SocketProtocolImp ;
37 class SocketProtocolSink ;
38}
39
40//| \class GNet::SocketProtocol
41/// An interface for implementing a low-level TLS/SSL protocol layer on top
42/// of a connected non-blocking socket.
43///
44/// Provides send() to send data, and onData() in a callback interface to
45/// receive data. The TLS/SSL socket protocol session is negotiated with the
46/// peer by calling secureConnect() or secureAccept(), and thereafter the
47/// interface is half-duplex. If no TLS/SSL session is in effect ('raw') then
48/// the protocol layer is transparent down to the socket.
49///
50/// The interface has read-event and write-event handlers that should be
51/// called when events are detected on the socket file descriptor. In raw
52/// mode the read handler delivers data via the onData() callback interface
53/// and the write handler is used to flush the output pipeline.
54///
56{
57public:
58 using Sink = SocketProtocolSink ;
59 G_EXCEPTION_CLASS( ReadError , "peer disconnected" ) ;
60 G_EXCEPTION( SendError , "peer disconnected" ) ;
61 G_EXCEPTION( ShutdownError , "shutdown error" ) ;
62 G_EXCEPTION( SecureConnectionTimeout , "secure connection timeout" ) ;
63
65 Sink & , StreamSocket & , unsigned int secure_connection_timeout ) ;
66 ///< Constructor. The references are kept.
67
69 ///< Destructor.
70
71 void readEvent() ;
72 ///< Called on receipt of a read event. Delivers data via the sink
73 ///< interface. Throws ReadError on error.
74
75 bool writeEvent() ;
76 ///< Called on receipt of a write event. Sends more pending data
77 ///< down the connection. Returns true if all pending data was
78 ///< sent. Throws SendError on error.
79
80 void otherEvent( EventHandler::Reason ) ;
81 ///< Called on receipt of an 'other' event. Throws an exception.
82 ///< For simple socket-close events (on Windows) the read queue
83 ///< is processed (see SocketProtocolSink::onData()) and the
84 ///< socket is shutdown() before the exception is thrown.
85
86 bool send( const std::string & data , std::size_t offset = 0U ) ;
87 ///< Sends data. Returns false if flow control asserted before
88 ///< all the data is sent. Returns true if all the data was sent,
89 ///< or if the data passed in (taking the offset into account)
90 ///< is empty. Throws SendError on error.
91 ///<
92 ///< If flow control is asserted then the socket write-event
93 ///< handler is installed and send() returns false. Unsent
94 ///< portions of the data string are copied internally. When
95 ///< the subsequent write-event is triggered the user should
96 ///< call writeEvent(). There should be no new calls to send()
97 ///< until writeEvent() returns true.
98
99 bool send( const std::vector<G::string_view> & data , std::size_t offset = 0U ) ;
100 ///< Overload to send data using scatter-gather segments.
101 ///< In this overload any unsent residue is not copied
102 ///< and the segment pointers must stay valid until
103 ///< writeEvent() returns true.
104
105 void shutdown() ;
106 ///< Initiates a TLS-close if secure, together with a
107 ///< Socket::shutdown(1).
108
109 static bool secureConnectCapable() ;
110 ///< Returns true if the implementation supports TLS/SSL and a
111 ///< "client" profile has been configured. See also GSsl::enabledAs().
112
113 void secureConnect() ;
114 ///< Initiates the TLS/SSL handshake, acting as a client.
115
116 static bool secureAcceptCapable() ;
117 ///< Returns true if the implementation supports TLS/SSL and a
118 ///< "server" profile has been configured. See also GSsl::enabledAs().
119
120 void secureAccept() ;
121 ///< Waits for the TLS/SSL handshake protocol, acting as a server.
122
123 bool secure() const ;
124 ///< Returns true if the connection is currently secure, ie. after
125 ///< onSecure().
126
127 std::string peerCertificate() const ;
128 ///< Returns the peer's TLS/SSL certificate or the empty
129 ///< string.
130
131 static void setReadBufferSize( std::size_t n ) ;
132 ///< Sets the read buffer size. Used in testing.
133
134public:
135 SocketProtocol( const SocketProtocol & ) = delete ;
136 SocketProtocol( SocketProtocol && ) = delete ;
137 void operator=( const SocketProtocol & ) = delete ;
138 void operator=( SocketProtocol && ) = delete ;
139
140private:
141 std::unique_ptr<SocketProtocolImp> m_imp ;
142} ;
143
144//| \class GNet::SocketProtocolSink
145/// An interface used by GNet::SocketProtocol to deliver data
146/// from a socket.
147///
149{
150public:
151 virtual ~SocketProtocolSink() = default ;
152 ///< Destructor.
153
154 virtual void onData( const char * , std::size_t ) = 0 ;
155 ///< Called when data is read from the socket.
156
157 virtual void onSecure( const std::string & peer_certificate ,
158 const std::string & protocol , const std::string & cipher ) = 0 ;
159 ///< Called once the secure socket protocol has
160 ///< been successfully negotiated.
161} ;
162
163#endif
A base class for classes that handle asynchronous events from the event loop.
Definition: geventhandler.h:48
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
An interface used by GNet::SocketProtocol to deliver data from a socket.
virtual ~SocketProtocolSink()=default
Destructor.
virtual void onSecure(const std::string &peer_certificate, const std::string &protocol, const std::string &cipher)=0
Called once the secure socket protocol has been successfully negotiated.
virtual void onData(const char *, std::size_t)=0
Called when data is read from the socket.
An interface for implementing a low-level TLS/SSL protocol layer on top of a connected non-blocking s...
bool send(const std::string &data, std::size_t offset=0U)
Sends data.
bool writeEvent()
Called on receipt of a write event.
void otherEvent(EventHandler::Reason)
Called on receipt of an 'other' event.
bool secure() const
Returns true if the connection is currently secure, ie.
static bool secureAcceptCapable()
Returns true if the implementation supports TLS/SSL and a "server" profile has been configured.
void secureAccept()
Waits for the TLS/SSL handshake protocol, acting as a server.
~SocketProtocol()
Destructor.
SocketProtocol(EventHandler &, ExceptionSink, Sink &, StreamSocket &, unsigned int secure_connection_timeout)
Constructor. The references are kept.
void shutdown()
Initiates a TLS-close if secure, together with a Socket::shutdown(1).
std::string peerCertificate() const
Returns the peer's TLS/SSL certificate or the empty string.
static bool secureConnectCapable()
Returns true if the implementation supports TLS/SSL and a "client" profile has been configured.
static void setReadBufferSize(std::size_t n)
Sets the read buffer size. Used in testing.
void readEvent()
Called on receipt of a read event.
void secureConnect()
Initiates the TLS/SSL handshake, acting as a client.
A derivation of GNet::Socket for a stream socket.
Definition: gsocket.h:311
Network classes.
Definition: gdef.h:1115