Skip to content

Commit e3a098c

Browse files
authored
Merge pull request #9 from KristianJerpetjon/0.13.x
microlb: tls refactoring
2 parents 4317157 + 03b3017 commit e3a098c

12 files changed

Lines changed: 767 additions & 364 deletions

File tree

api/net/openssl/tls_stream.hpp

Lines changed: 10 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
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

1414
namespace 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

Comments
 (0)