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,35 +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_data (DataCallback cb) override {
47- m_on_data = std::move (cb);
48- }
49- size_t next_size () override {
50- // FIXME: implement buffering for read_next
51- return 0 ;
52- }
53- buffer_t read_next () override {
54- // FIXME: implement buffering for read_next
55- return {};
56- }
57- void on_close (CloseCallback cb) override {
58- m_on_close = std::move (cb);
59- }
60- void on_write (WriteCallback cb) override {
61- m_on_write = std::move (cb);
62- }
63-
6439 bool is_connected () const noexcept override {
6540 return handshake_completed () && m_transport->is_connected ();
6641 }
6742 bool is_writable () const noexcept override {
68- return is_connected () && m_transport->is_writable ();
43+ return ( not write_congested ()) && is_connected () && m_transport->is_writable ();
6944 }
7045 bool is_readable () const noexcept override {
7146 return m_transport->is_readable ();
@@ -87,7 +62,12 @@ namespace openssl
8762
8863 size_t serialize_to (void *) const override ;
8964
65+ void handle_read_congestion () override ;
66+ void handle_write_congestion () override ;
9067 private:
68+ void handle_data ();
69+ int decrypt (const void *data,int size);
70+ int send_decrypted ();
9171 void tls_read (buffer_t );
9272 int tls_perform_stream_write ();
9373 int tls_perform_handshake ();
@@ -100,273 +80,12 @@ namespace openssl
10080 STATUS_FAIL
10181 };
10282 status_t status (int n) const noexcept ;
103-
10483 Stream_ptr m_transport = nullptr ;
10584 SSL* m_ssl = nullptr ;
10685 BIO* m_bio_rd = nullptr ;
10786 BIO* m_bio_wr = nullptr ;
10887 bool m_busy = false ;
10988 bool m_deferred_close = false ;
110- ConnectCallback m_on_connect = nullptr ;
111- ReadCallback m_on_read = nullptr ;
112- DataCallback m_on_data = nullptr ;
113- WriteCallback m_on_write = nullptr ;
114- CloseCallback m_on_close = nullptr ;
11589 };
11690
117- inline TLS_stream::TLS_stream (SSL_CTX* ctx, Stream_ptr t, bool outgoing)
118- : m_transport(std::move(t))
119- {
120- ERR_clear_error (); // prevent old errors from mucking things up
121- this ->m_bio_rd = BIO_new (BIO_s_mem ());
122- this ->m_bio_wr = BIO_new (BIO_s_mem ());
123- assert (ERR_get_error () == 0 && " Initializing BIOs" );
124- this ->m_ssl = SSL_new (ctx);
125- assert (this ->m_ssl != nullptr );
126- assert (ERR_get_error () == 0 && " Initializing SSL" );
127- // TLS server-mode
128- if (outgoing == false )
129- SSL_set_accept_state (this ->m_ssl );
130- else
131- SSL_set_connect_state (this ->m_ssl );
132-
133- SSL_set_bio (this ->m_ssl , this ->m_bio_rd , this ->m_bio_wr );
134- // always-on callbacks
135- // FIXME: consider using on_data as the default always-on event.
136- m_transport->on_read (8192 , {this , &TLS_stream::tls_read});
137- m_transport->on_close ({this , &TLS_stream::close_callback_once});
138-
139- // start TLS handshake process
140- if (outgoing == true )
141- {
142- if (this ->tls_perform_handshake () < 0 ) return ;
143- }
144- }
145- inline TLS_stream::TLS_stream (Stream_ptr t, SSL* ssl, BIO* rd, BIO* wr)
146- : m_transport(std::move(t)), m_ssl(ssl), m_bio_rd(rd), m_bio_wr(wr)
147- {
148- // always-on callbacks
149- m_transport->on_read (8192 , {this , &TLS_stream::tls_read});
150- m_transport->on_close ({this , &TLS_stream::close_callback_once});
151- }
152- inline TLS_stream::~TLS_stream ()
153- {
154- assert (m_busy == false && " Cannot delete stream while in its call stack" );
155- SSL_free (this ->m_ssl );
156- }
157-
158- inline void TLS_stream::write (buffer_t buffer)
159- {
160- if (UNLIKELY (this ->is_connected () == false )) {
161- TLS_PRINT (" TLS_stream::write() called on closed stream\n " );
162- return ;
163- }
164-
165- int n = SSL_write (this ->m_ssl , buffer->data (), buffer->size ());
166- auto status = this ->status (n);
167- if (status == STATUS_FAIL) {
168- this ->close ();
169- return ;
170- }
171-
172- do {
173- n = tls_perform_stream_write ();
174- } while (n > 0 );
175- }
176- inline void TLS_stream::write (const std::string& str)
177- {
178- write (net::Stream::construct_buffer (str.data (), str.data () + str.size ()));
179- }
180- inline void TLS_stream::write (const void * data, const size_t len)
181- {
182- auto * buf = static_cast <const uint8_t *> (data);
183- write (net::Stream::construct_buffer (buf, buf + len));
184- }
185-
186- inline void TLS_stream::tls_read (buffer_t buffer)
187- {
188- ERR_clear_error ();
189- uint8_t * buf = buffer->data ();
190- int len = buffer->size ();
191-
192- while (len > 0 )
193- {
194- int n = BIO_write (this ->m_bio_rd , buf, len);
195- if (UNLIKELY (n < 0 )) {
196- this ->close ();
197- return ;
198- }
199- buf += n;
200- len -= n;
201-
202- // if we aren't finished initializing session
203- if (UNLIKELY (!handshake_completed ()))
204- {
205- int num = SSL_do_handshake (this ->m_ssl );
206- auto status = this ->status (num);
207-
208- // OpenSSL wants to write
209- if (status == STATUS_WANT_IO)
210- {
211- tls_perform_stream_write ();
212- }
213- else if (status == STATUS_FAIL)
214- {
215- if (num < 0 ) {
216- TLS_PRINT (" TLS_stream::SSL_do_handshake() returned %d\n " , num);
217- #ifdef VERBOSE_OPENSSL
218- ERR_print_errors_fp (stdout);
219- #endif
220- }
221- this ->close ();
222- return ;
223- }
224- // nothing more to do if still not finished
225- if (handshake_completed () == false ) return ;
226- // handshake success
227- if (m_on_connect) m_on_connect (*this );
228- }
229-
230- // read decrypted data
231- do {
232- char temp[8192 ];
233- n = SSL_read (this ->m_ssl , temp, sizeof (temp));
234- if (n > 0 ) {
235- auto buf = net::Stream::construct_buffer (temp, temp + n);
236- if (m_on_read) {
237- this ->m_busy = true ;
238- m_on_read (std::move (buf));
239- this ->m_busy = false ;
240- }
241- }
242- } while (n > 0 );
243- // this goes here?
244- if (UNLIKELY (this ->is_closing () || this ->is_closed ())) {
245- TLS_PRINT (" TLS_stream::SSL_read closed during read\n " );
246- return ;
247- }
248- if (this ->m_deferred_close ) {
249- this ->close (); return ;
250- }
251-
252- auto status = this ->status (n);
253- // did peer request stream renegotiation?
254- if (status == STATUS_WANT_IO)
255- {
256- do {
257- n = tls_perform_stream_write ();
258- } while (n > 0 );
259- }
260- else if (status == STATUS_FAIL)
261- {
262- this ->close ();
263- return ;
264- }
265- // check deferred closing
266- if (this ->m_deferred_close ) {
267- this ->close (); return ;
268- }
269-
270- } // while it < end
271- } // tls_read()
272-
273- inline int TLS_stream::tls_perform_stream_write ()
274- {
275- ERR_clear_error ();
276- int pending = BIO_ctrl_pending (this ->m_bio_wr );
277- // printf("pending: %d\n", pending);
278- if (pending > 0 )
279- {
280- auto buffer = net::Stream::construct_buffer (pending);
281- int n = BIO_read (this ->m_bio_wr , buffer->data (), buffer->size ());
282- assert (n == pending);
283- m_transport->write (buffer);
284- if (m_on_write) {
285- this ->m_busy = true ;
286- m_on_write (n);
287- this ->m_busy = false ;
288- }
289- return n;
290- }
291- else {
292- BIO_read (this ->m_bio_wr , nullptr , 0 );
293- }
294- if (!BIO_should_retry (this ->m_bio_wr ))
295- {
296- this ->close ();
297- return -1 ;
298- }
299- return 0 ;
300- }
301- inline int TLS_stream::tls_perform_handshake ()
302- {
303- ERR_clear_error (); // prevent old errors from mucking things up
304- // will return -1:SSL_ERROR_WANT_WRITE
305- int ret = SSL_do_handshake (this ->m_ssl );
306- int n = this ->status (ret);
307- ERR_print_errors_fp (stderr);
308- if (n == STATUS_WANT_IO)
309- {
310- do {
311- n = tls_perform_stream_write ();
312- if (n < 0 ) {
313- TLS_PRINT (" TLS_stream::tls_perform_handshake() stream write failed\n " );
314- }
315- } while (n > 0 );
316- return n;
317- }
318- else {
319- TLS_PRINT (" TLS_stream::tls_perform_handshake() returned %d\n " , ret);
320- this ->close ();
321- return -1 ;
322- }
323- }
324-
325- inline void TLS_stream::close ()
326- {
327- // ERR_clear_error();
328- if (this ->m_busy ) {
329- this ->m_deferred_close = true ; return ;
330- }
331- CloseCallback func = std::move (this ->m_on_close );
332- this ->reset_callbacks ();
333- if (m_transport->is_connected ())
334- m_transport->close ();
335- if (func) func ();
336- }
337- inline void TLS_stream::close_callback_once ()
338- {
339- if (this ->m_busy ) {
340- this ->m_deferred_close = true ; return ;
341- }
342- CloseCallback func = std::move (this ->m_on_close );
343- this ->reset_callbacks ();
344- if (func) func ();
345- }
346- inline void TLS_stream::reset_callbacks ()
347- {
348- this ->m_on_close = nullptr ;
349- this ->m_on_connect = nullptr ;
350- this ->m_on_read = nullptr ;
351- this ->m_on_write = nullptr ;
352- }
353-
354- inline bool TLS_stream::handshake_completed () const noexcept
355- {
356- return SSL_is_init_finished (this ->m_ssl );
357- }
358- inline TLS_stream::status_t TLS_stream::status (int n) const noexcept
359- {
360- int error = SSL_get_error (this ->m_ssl , n);
361- switch (error)
362- {
363- case SSL_ERROR_NONE:
364- return STATUS_OK;
365- case SSL_ERROR_WANT_WRITE:
366- case SSL_ERROR_WANT_READ:
367- return STATUS_WANT_IO;
368- default :
369- return STATUS_FAIL;
370- }
371- }
37291} // openssl
0 commit comments