Skip to content

Commit

Permalink
tls session progress
Browse files Browse the repository at this point in the history
  • Loading branch information
weyrick committed Nov 15, 2023
1 parent 5b0f6f6 commit 58e1c3e
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 29 deletions.
105 changes: 79 additions & 26 deletions libs/visor_http_client/httpssession.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <algorithm>
#include <cstring>
#include <iostream>
#include <uvw/tcp.h>

#include "httpssession.h"

Expand Down Expand Up @@ -47,7 +48,7 @@ std::unique_ptr<http2_stream_data> HTTPSSession::create_http2_stream_data(std::u
}
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))

static ssize_t send_callback([[maybe_unused]] nghttp2_session *session, const uint8_t *data,
static ssize_t ng2_send_callback([[maybe_unused]] nghttp2_session *session, const uint8_t *data,
size_t length, [[maybe_unused]] int flags, void *user_data)
{
auto class_session = static_cast<HTTPSSession *>(user_data);
Expand Down Expand Up @@ -78,7 +79,7 @@ void HTTPSSession::process_receive(const uint8_t *data, size_t len)
_got_dns_msg(std::move(buf), len);
}

static int on_data_chunk_recv_callback(nghttp2_session *session, [[maybe_unused]] uint8_t flags,
static int ng2_on_data_chunk_recv_callback(nghttp2_session *session, [[maybe_unused]] uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data)
{
Expand All @@ -97,7 +98,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, [[maybe_unused]
return 0;
}

static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, [[maybe_unused]] uint32_t error_code,
static int ng2_on_stream_close_callback(nghttp2_session *session, int32_t stream_id, [[maybe_unused]] uint32_t error_code,
[[maybe_unused]] void *user_data)
{
auto stream_data = static_cast<http2_stream_data *>(nghttp2_session_get_stream_user_data(session, stream_id));
Expand All @@ -109,7 +110,7 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
return 0;
}

int on_frame_recv_callback([[maybe_unused]] nghttp2_session *session,
int ng2_on_frame_recv_callback([[maybe_unused]] nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
auto class_session = static_cast<HTTPSSession *>(user_data);
Expand All @@ -130,13 +131,48 @@ void HTTPSSession::init_nghttp2()
{
nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_send_callback(callbacks, ng2_send_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, ng2_on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, ng2_on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, ng2_on_frame_recv_callback);
nghttp2_session_client_new(&_current_session, callbacks, this);
nghttp2_session_callbacks_del(callbacks);
}
#define WHERE_INFO(ssl, w, flag, msg) { \
if(w & flag) { \
printf("\t"); \
printf(msg); \
printf(" - %s ", SSL_state_string(ssl)); \
printf(" - %s ", SSL_state_string_long(ssl)); \
printf("\n"); \
}\
}

// INFO CALLBACK
void dummy_ssl_info_callback(const SSL* ssl, int where, int ret) {
if(ret == 0) {
printf("dummy_ssl_info_callback, error occured.\n");
return;
}
WHERE_INFO(ssl, where, SSL_CB_LOOP, "LOOP");
WHERE_INFO(ssl, where, SSL_CB_EXIT, "EXIT");
WHERE_INFO(ssl, where, SSL_CB_READ, "READ");
WHERE_INFO(ssl, where, SSL_CB_WRITE, "WRITE");
WHERE_INFO(ssl, where, SSL_CB_ALERT, "ALERT");
WHERE_INFO(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
}
void dummy_ssl_msg_callback(
int writep
,int version
,int contentType
,const void* buf
,size_t len
,SSL* ssl
,void *arg
)
{
printf("\tMessage callback with length: %zu\n", len);
}

bool HTTPSSession::setup()
{
Expand Down Expand Up @@ -170,7 +206,12 @@ bool HTTPSSession::setup()
std::cerr << "OpenSSL failed to create SSL session." << std::endl;
return false;
}

SSL_CTX_set_info_callback(_ssl_context, dummy_ssl_info_callback);
SSL_CTX_set_msg_callback(_ssl_context, dummy_ssl_msg_callback);
_read_bio = BIO_new(BIO_s_mem());
_write_bio = BIO_new(BIO_s_mem());
SSL_set_bio(_ssl_session, _read_bio, _write_bio);
SSL_set_connect_state(_ssl_session);
return true;
}
void HTTPSSession::send_settings()
Expand Down Expand Up @@ -276,10 +317,20 @@ void HTTPSSession::write(std::unique_ptr<char[]> data, size_t len)
std::cerr << "HTTP2 failed to send" << std::endl;
}
}

void HTTPSSession::flush_read_bio() {
char buf[1024*16];
int bytes_read = 0;
while((bytes_read = BIO_read(_write_bio, buf, sizeof(buf))) > 0) {
std::cerr << "flush_read_bio: " << buf << std::endl;
// WRITE TO STREAM
_handle->write(buf, bytes_read);
}
}
void HTTPSSession::receive_data(const char data[], size_t _len)
{
_pull_buffer.append(data, _len);
std::cerr << "receive_data: " << data << std::endl;
int written = BIO_write(_read_bio, data, _len);
// _pull_buffer.append(data, _len);
switch (_tls_state) {
case LinkState::HANDSHAKE:
do_handshake();
Expand All @@ -294,9 +345,9 @@ void HTTPSSession::receive_data(const char data[], size_t _len)
int error = SSL_get_error(_ssl_session, len);
if (error == SSL_ERROR_WANT_READ) {
// OpenSSL wants to read more data. Check if we don't have any data left to read.
if (_pull_buffer.empty()) {
break;
}
// if (_pull_buffer.empty()) {
// break;
// }
continue;
} else if (error == SSL_ERROR_WANT_WRITE) {
// OpenSSL wants to write data (e.g., for renegotiation). Continue processing.
Expand Down Expand Up @@ -325,16 +376,16 @@ void HTTPSSession::send_tls(void *data, size_t len)

void HTTPSSession::do_handshake()
{
int err = SSL_connect(_ssl_session); // Assuming client-side. Use SSL_accept for server-side.
int err = SSL_connect(_ssl_session); // client-side
if (err == 1) { // Successful handshake
const unsigned char *alpn = NULL;
unsigned int alpnlen = 0;
SSL_get0_alpn_selected(_ssl_session, &alpn, &alpnlen);
if (!alpn || alpnlen != 2 || memcmp(alpn, "h2", 2) != 0) {
std::cerr << "Cannot get ALPN or ALPN is not 'h2'." << std::endl;
close();
return;
}
// const unsigned char *alpn = NULL;
// unsigned int alpnlen = 0;
// SSL_get0_alpn_selected(_ssl_session, &alpn, &alpnlen);
// if (!alpn || alpnlen != 2 || memcmp(alpn, "h2", 2) != 0) {
// std::cerr << "Cannot get ALPN or ALPN is not 'h2'." << std::endl;
// close();
// return;
// }
init_nghttp2();
send_settings();
if (session_send() != 0) {
Expand All @@ -351,9 +402,11 @@ void HTTPSSession::do_handshake()
std::cerr << "Handshake failed: syscall error" << std::endl;
ERR_print_errors_fp(stderr);
_handshake_error();
} else if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
// Non-fatal error. OpenSSL wants to either read or write.
std::cout << "Handshake needs more processing. Continue calling do_handshake()." << std::endl;
} else if (error == SSL_ERROR_WANT_READ) {
std::cout << "Handshake needs READ" << std::endl;
flush_read_bio();
} else if (error == SSL_ERROR_WANT_WRITE) {
std::cout << "Handshake needs WRITE" << std::endl;
} else {
std::cerr << "Unknown handshake error." << std::endl;
}
Expand Down
5 changes: 4 additions & 1 deletion libs/visor_http_client/httpssession.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,11 @@ class HTTPSSession : public TCPSession
HTTPMethod _method;

nghttp2_session *_current_session;
std::string _pull_buffer;
// std::string _pull_buffer;

SSL *_ssl_session;
SSL_CTX *_ssl_context;
BIO *_read_bio;
BIO *_write_bio;
void flush_read_bio();
};
5 changes: 3 additions & 2 deletions libs/visor_http_client/test_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ void connect_tcp_events(std::shared_ptr<uvw::tcp_handle> tcp_handle, std::shared

// SOCKET: local socket was closed, cleanup resources and possibly restart another connection
tcp_handle->on<uvw::close_event>([](uvw::close_event &, uvw::tcp_handle &handle) {
std::cerr << "close_event" << std::endl;
handle.stop();
});

Expand Down Expand Up @@ -57,10 +58,10 @@ void connect_tcp_events(std::shared_ptr<uvw::tcp_handle> tcp_handle, std::shared
// SOCKET: on connect
tcp_handle->on<uvw::connect_event>([tcp_session](uvw::connect_event &, uvw::tcp_handle &handle) {
std::cerr << "ConnectEvent" << std::endl;
tcp_session->on_connect_event();

// start reading from incoming stream, fires data_event when receiving
handle.read();
tcp_session->on_connect_event();

});
}

Expand Down

0 comments on commit 58e1c3e

Please sign in to comment.