22#include < openssl/err.h>
33#include < openssl/pem.h>
44#include < openssl/ssl.h>
5- #include < net/stream .hpp>
5+ #include < net/stream_buffer .hpp>
66
7- // #define VERBOSE_OPENSSL
7+ // #define VERBOSE_OPENSSL 0
88#ifdef VERBOSE_OPENSSL
9- #define TLS_PRINT (fmt, ...) printf(fmt, ##__VA_ARGS__)
9+ #define TLS_PRINT (fmt, ...) printf(" TLS_Stream " );printf( fmt, ##__VA_ARGS__)
1010#else
1111#define TLS_PRINT (fmt, ...) /* fmt */
1212#endif
1313
1414namespace openssl
1515{
16- struct TLS_stream : public net ::Stream
16+ struct TLS_stream : public net ::StreamBuffer
1717 {
1818 using Stream_ptr = net::Stream_ptr;
1919
@@ -25,7 +25,6 @@ namespace openssl
2525 void write (const std::string&) override ;
2626 void write (const void * buf, size_t n) override ;
2727 void close () override ;
28- void reset_callbacks () override ;
2928
3029 net::Socket local () const override {
3130 return m_transport->local ();
@@ -37,24 +36,11 @@ namespace openssl
3736 return m_transport->to_string ();
3837 }
3938
40- void on_connect (ConnectCallback cb) override {
41- m_on_connect = std::move (cb);
42- }
43- void on_read (size_t , ReadCallback cb) override {
44- m_on_read = std::move (cb);
45- }
46- void on_close (CloseCallback cb) override {
47- m_on_close = std::move (cb);
48- }
49- void on_write (WriteCallback cb) override {
50- m_on_write = std::move (cb);
51- }
52-
5339 bool is_connected () const noexcept override {
5440 return handshake_completed () && m_transport->is_connected ();
5541 }
5642 bool is_writable () const noexcept override {
57- return is_connected () && m_transport->is_writable ();
43+ return ( not write_congested ()) && is_connected () && m_transport->is_writable ();
5844 }
5945 bool is_readable () const noexcept override {
6046 return m_transport->is_readable ();
@@ -76,7 +62,12 @@ namespace openssl
7662
7763 size_t serialize_to (void *) const override ;
7864
65+ void handle_read_congestion () override ;
66+ void handle_write_congestion () override ;
7967 private:
68+ void handle_data ();
69+ int decrypt (const void *data,int size);
70+ int send_decrypted ();
8071 void tls_read (buffer_t );
8172 int tls_perform_stream_write ();
8273 int tls_perform_handshake ();
@@ -89,271 +80,12 @@ namespace openssl
8980 STATUS_FAIL
9081 };
9182 status_t status (int n) const noexcept ;
92-
9383 Stream_ptr m_transport = nullptr ;
9484 SSL* m_ssl = nullptr ;
9585 BIO* m_bio_rd = nullptr ;
9686 BIO* m_bio_wr = nullptr ;
9787 bool m_busy = false ;
9888 bool m_deferred_close = false ;
99- ConnectCallback m_on_connect = nullptr ;
100- ReadCallback m_on_read = nullptr ;
101- WriteCallback m_on_write = nullptr ;
102- CloseCallback m_on_close = nullptr ;
10389 };
10490
105- inline TLS_stream::TLS_stream (SSL_CTX* ctx, Stream_ptr t, bool outgoing)
106- : m_transport(std::move(t))
107- {
108- ERR_clear_error (); // prevent old errors from mucking things up
109- this ->m_bio_rd = BIO_new (BIO_s_mem ());
110- this ->m_bio_wr = BIO_new (BIO_s_mem ());
111- assert (ERR_get_error () == 0 && " Initializing BIOs" );
112- this ->m_ssl = SSL_new (ctx);
113- assert (this ->m_ssl != nullptr );
114- assert (ERR_get_error () == 0 && " Initializing SSL" );
115- // TLS server-mode
116- if (outgoing == false )
117- SSL_set_accept_state (this ->m_ssl );
118- else
119- SSL_set_connect_state (this ->m_ssl );
120-
121- SSL_set_bio (this ->m_ssl , this ->m_bio_rd , this ->m_bio_wr );
122- // always-on callbacks
123- m_transport->on_read (8192 , {this , &TLS_stream::tls_read});
124- m_transport->on_close ({this , &TLS_stream::close_callback_once});
125-
126- // start TLS handshake process
127- if (outgoing == true )
128- {
129- if (this ->tls_perform_handshake () < 0 ) return ;
130- }
131- }
132- inline TLS_stream::TLS_stream (Stream_ptr t, SSL* ssl, BIO* rd, BIO* wr)
133- : m_transport(std::move(t)), m_ssl(ssl), m_bio_rd(rd), m_bio_wr(wr)
134- {
135- // always-on callbacks
136- m_transport->on_read (8192 , {this , &TLS_stream::tls_read});
137- m_transport->on_close ({this , &TLS_stream::close_callback_once});
138- }
139- inline TLS_stream::~TLS_stream ()
140- {
141- assert (m_busy == false && " Cannot delete stream while in its call stack" );
142- SSL_free (this ->m_ssl );
143- }
144-
145- inline void TLS_stream::write (buffer_t buffer)
146- {
147- if (UNLIKELY (this ->is_connected () == false )) {
148- TLS_PRINT (" TLS_stream::write() called on closed stream\n " );
149- return ;
150- }
151-
152- int n = SSL_write (this ->m_ssl , buffer->data (), buffer->size ());
153- auto status = this ->status (n);
154- if (status == STATUS_FAIL) {
155- this ->close ();
156- return ;
157- }
158-
159- do {
160- n = tls_perform_stream_write ();
161- } while (n > 0 );
162- }
163- inline void TLS_stream::write (const std::string& str)
164- {
165- write (net::Stream::construct_buffer (str.data (), str.data () + str.size ()));
166- }
167- inline void TLS_stream::write (const void * data, const size_t len)
168- {
169- auto * buf = static_cast <const uint8_t *> (data);
170- write (net::Stream::construct_buffer (buf, buf + len));
171- }
172-
173- inline void TLS_stream::tls_read (buffer_t buffer)
174- {
175- ERR_clear_error ();
176- uint8_t * buf = buffer->data ();
177- int len = buffer->size ();
178-
179- while (len > 0 )
180- {
181- int n = BIO_write (this ->m_bio_rd , buf, len);
182- if (UNLIKELY (n < 0 )) {
183- this ->close ();
184- return ;
185- }
186- buf += n;
187- len -= n;
188-
189- // if we aren't finished initializing session
190- if (UNLIKELY (!handshake_completed ()))
191- {
192- int num = SSL_do_handshake (this ->m_ssl );
193- auto status = this ->status (num);
194-
195- // OpenSSL wants to write
196- if (status == STATUS_WANT_IO)
197- {
198- tls_perform_stream_write ();
199- }
200- else if (status == STATUS_FAIL)
201- {
202- if (num < 0 ) {
203- TLS_PRINT (" TLS_stream::SSL_do_handshake() returned %d\n " , num);
204- #ifdef VERBOSE_OPENSSL
205- ERR_print_errors_fp (stdout);
206- #endif
207- }
208- this ->close ();
209- return ;
210- }
211- // nothing more to do if still not finished
212- if (handshake_completed () == false ) return ;
213- // handshake success
214- if (m_on_connect) m_on_connect (*this );
215- }
216-
217- // read decrypted data
218- do {
219- char temp[8192 ];
220- n = SSL_read (this ->m_ssl , temp, sizeof (temp));
221- if (n > 0 ) {
222- auto buf = net::Stream::construct_buffer (temp, temp + n);
223- if (m_on_read) {
224- this ->m_busy = true ;
225- m_on_read (std::move (buf));
226- this ->m_busy = false ;
227- }
228- }
229- } while (n > 0 );
230- // this goes here?
231- if (UNLIKELY (this ->is_closing () || this ->is_closed ())) {
232- TLS_PRINT (" TLS_stream::SSL_read closed during read\n " );
233- return ;
234- }
235- if (this ->m_deferred_close ) {
236- this ->close (); return ;
237- }
238-
239- auto status = this ->status (n);
240- // did peer request stream renegotiation?
241- if (status == STATUS_WANT_IO)
242- {
243- do {
244- n = tls_perform_stream_write ();
245- } while (n > 0 );
246- }
247- else if (status == STATUS_FAIL)
248- {
249- this ->close ();
250- return ;
251- }
252- // check deferred closing
253- if (this ->m_deferred_close ) {
254- this ->close (); return ;
255- }
256-
257- } // while it < end
258- } // tls_read()
259-
260- inline int TLS_stream::tls_perform_stream_write ()
261- {
262- ERR_clear_error ();
263- int pending = BIO_ctrl_pending (this ->m_bio_wr );
264- // printf("pending: %d\n", pending);
265- if (pending > 0 )
266- {
267- auto buffer = net::Stream::construct_buffer (pending);
268- int n = BIO_read (this ->m_bio_wr , buffer->data (), buffer->size ());
269- assert (n == pending);
270- m_transport->write (buffer);
271- if (m_on_write) {
272- this ->m_busy = true ;
273- m_on_write (n);
274- this ->m_busy = false ;
275- }
276- return n;
277- }
278- else {
279- BIO_read (this ->m_bio_wr , nullptr , 0 );
280- }
281- if (!BIO_should_retry (this ->m_bio_wr ))
282- {
283- this ->close ();
284- return -1 ;
285- }
286- return 0 ;
287- }
288- inline int TLS_stream::tls_perform_handshake ()
289- {
290- ERR_clear_error (); // prevent old errors from mucking things up
291- // will return -1:SSL_ERROR_WANT_WRITE
292- int ret = SSL_do_handshake (this ->m_ssl );
293- int n = this ->status (ret);
294- ERR_print_errors_fp (stderr);
295- if (n == STATUS_WANT_IO)
296- {
297- do {
298- n = tls_perform_stream_write ();
299- if (n < 0 ) {
300- TLS_PRINT (" TLS_stream::tls_perform_handshake() stream write failed\n " );
301- }
302- } while (n > 0 );
303- return n;
304- }
305- else {
306- TLS_PRINT (" TLS_stream::tls_perform_handshake() returned %d\n " , ret);
307- this ->close ();
308- return -1 ;
309- }
310- }
311-
312- inline void TLS_stream::close ()
313- {
314- // ERR_clear_error();
315- if (this ->m_busy ) {
316- this ->m_deferred_close = true ; return ;
317- }
318- CloseCallback func = std::move (this ->m_on_close );
319- this ->reset_callbacks ();
320- if (m_transport->is_connected ())
321- m_transport->close ();
322- if (func) func ();
323- }
324- inline void TLS_stream::close_callback_once ()
325- {
326- if (this ->m_busy ) {
327- this ->m_deferred_close = true ; return ;
328- }
329- CloseCallback func = std::move (this ->m_on_close );
330- this ->reset_callbacks ();
331- if (func) func ();
332- }
333- inline void TLS_stream::reset_callbacks ()
334- {
335- this ->m_on_close = nullptr ;
336- this ->m_on_connect = nullptr ;
337- this ->m_on_read = nullptr ;
338- this ->m_on_write = nullptr ;
339- }
340-
341- inline bool TLS_stream::handshake_completed () const noexcept
342- {
343- return SSL_is_init_finished (this ->m_ssl );
344- }
345- inline TLS_stream::status_t TLS_stream::status (int n) const noexcept
346- {
347- int error = SSL_get_error (this ->m_ssl , n);
348- switch (error)
349- {
350- case SSL_ERROR_NONE:
351- return STATUS_OK;
352- case SSL_ERROR_WANT_WRITE:
353- case SSL_ERROR_WANT_READ:
354- return STATUS_WANT_IO;
355- default :
356- return STATUS_FAIL;
357- }
358- }
35991} // openssl
0 commit comments