|
|
|
@ -27,10 +27,19 @@ static void parse_http_headers(std::string & res, http_response_t *parsed); |
|
|
|
|
|
|
|
|
|
struct http_co_t |
|
|
|
|
{ |
|
|
|
|
#ifdef WITH_OPENSSL |
|
|
|
|
static SSL_CTX *ssl_ctx = NULL; |
|
|
|
|
SSL *ssl_cli = NULL; |
|
|
|
|
BIO *ssl_rbio = NULL; |
|
|
|
|
BIO *ssl_wbio = NULL; |
|
|
|
|
std::vector<uint8_t> encrypted_out; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
timerfd_manager_t *tfd; |
|
|
|
|
std::function<void(const http_response_t*)> response_callback; |
|
|
|
|
|
|
|
|
|
int request_timeout = 0; |
|
|
|
|
bool ssl = false; |
|
|
|
|
std::string host; |
|
|
|
|
std::string request; |
|
|
|
|
std::string ws_outbox; |
|
|
|
@ -259,6 +268,12 @@ void http_response_t::parse_json_response(std::string & error, json11::Json & r) |
|
|
|
|
|
|
|
|
|
http_co_t::~http_co_t() |
|
|
|
|
{ |
|
|
|
|
#ifdef WITH_OPENSSL |
|
|
|
|
if (ssl_cli) |
|
|
|
|
{ |
|
|
|
|
SSL_free(ssl_cli); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
close_connection(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -304,6 +319,27 @@ void http_co_t::start_connection() |
|
|
|
|
} |
|
|
|
|
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK); |
|
|
|
|
epoll_events = 0; |
|
|
|
|
#ifdef WITH_OPENSSL |
|
|
|
|
// https://wiki.openssl.org/index.php/Hostname_validation
|
|
|
|
|
if (ssl) |
|
|
|
|
{ |
|
|
|
|
if (!ssl_ctx) |
|
|
|
|
ssl_ctx = SSL_CTX_new(TLS_method()); |
|
|
|
|
ssl_rbio = BIO_new(BIO_s_mem()); |
|
|
|
|
ssl_wbio = BIO_new(BIO_s_mem()); |
|
|
|
|
ssl_cli = SSL_new(ssl_ctx); |
|
|
|
|
if (!ssl_ctx || !ssl_cli || !ssl_rbio || !ssl_wbio) |
|
|
|
|
{ |
|
|
|
|
parsed = { .error = std::string("openssl initialization failed: ")+ERR_get_error(NULL) }; |
|
|
|
|
response_callback(&parsed); |
|
|
|
|
response_callback = NULL; |
|
|
|
|
stackout(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
SSL_set_connect_state(ssl_cli); |
|
|
|
|
SSL_set_bio(ssl_cli, ssl_rbio, ssl_wbio); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
// Finally call connect
|
|
|
|
|
int r = ::connect(peer_fd, (sockaddr*)&addr, sizeof(addr)); |
|
|
|
|
if (r < 0 && errno != EINPROGRESS) |
|
|
|
@ -353,6 +389,35 @@ void http_co_t::handle_events() |
|
|
|
|
stackout(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void http_co_t::do_ssl_handshake() |
|
|
|
|
{ |
|
|
|
|
int r = SSL_do_handshake(ssl_cli); |
|
|
|
|
if (r == SSL_ERROR_WANT_WRITE) |
|
|
|
|
{ |
|
|
|
|
// Queue outbound TLS data
|
|
|
|
|
while (true) |
|
|
|
|
{ |
|
|
|
|
if (encrypted_out.size() < encrypted_out.capacity()+512) |
|
|
|
|
encrypted_out.reserve(encrypted_out.capacity()*2); |
|
|
|
|
r = BIO_read(ssl_wbio, encrypted_out.data()+encrypted_out.size(), encrypted_out.capacity()-encrypted_out.size()); |
|
|
|
|
if (r <= 0 && !BIO_should_retry(client.wbio)) |
|
|
|
|
return SSL_ERROR_SYSCALL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (r == SSL_ERROR_WANT_READ) |
|
|
|
|
{ |
|
|
|
|
// Wait until we have more incoming data
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
else if (r == SSL_ERROR_NONE) |
|
|
|
|
{ |
|
|
|
|
ssl_handshake_done = true; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
// Error
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void http_co_t::handle_connect_result() |
|
|
|
|
{ |
|
|
|
|
stackin(); |
|
|
|
|