Extract common HTTP context
This commit is contained in:
@@ -30,6 +30,11 @@ etcd_state_client_t::~etcd_state_client_t()
|
|||||||
http_destroy(keepalive_client);
|
http_destroy(keepalive_client);
|
||||||
keepalive_client = NULL;
|
keepalive_client = NULL;
|
||||||
}
|
}
|
||||||
|
if (http_ctx)
|
||||||
|
{
|
||||||
|
http_context_destroy(http_ctx);
|
||||||
|
http_ctx = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (load_pgs_timer_id >= 0)
|
if (load_pgs_timer_id >= 0)
|
||||||
{
|
{
|
||||||
@@ -72,6 +77,21 @@ std::vector<std::string> etcd_state_client_t::get_addresses()
|
|||||||
return addrs;
|
return addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
http_context_t *etcd_state_client_t::get_http_ctx()
|
||||||
|
{
|
||||||
|
if (!http_ctx)
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
http_ctx = http_context_init(etcd_client_cert, etcd_client_key, etcd_ca, error);
|
||||||
|
if (!http_ctx)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to initialize HTTP context: %s\n", error.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return http_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
void etcd_state_client_t::etcd_call_oneshot(std::string etcd_address, std::string api, json11::Json payload,
|
void etcd_state_client_t::etcd_call_oneshot(std::string etcd_address, std::string api, json11::Json payload,
|
||||||
int timeout, std::function<void(std::string, json11::Json)> callback)
|
int timeout, std::function<void(std::string, json11::Json)> callback)
|
||||||
{
|
{
|
||||||
@@ -91,7 +111,7 @@ void etcd_state_client_t::etcd_call_oneshot(std::string etcd_address, std::strin
|
|||||||
"Content-Length: "+std::to_string(req.size())+"\r\n"
|
"Content-Length: "+std::to_string(req.size())+"\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n"
|
||||||
"\r\n"+req;
|
"\r\n"+req;
|
||||||
auto http_cli = http_init(tfd);
|
auto http_cli = http_init(tfd, get_http_ctx());
|
||||||
auto cb = [http_cli, callback](const http_response_t *response)
|
auto cb = [http_cli, callback](const http_response_t *response)
|
||||||
{
|
{
|
||||||
std::string err;
|
std::string err;
|
||||||
@@ -100,7 +120,7 @@ void etcd_state_client_t::etcd_call_oneshot(std::string etcd_address, std::strin
|
|||||||
callback(err, data);
|
callback(err, data);
|
||||||
http_destroy(http_cli);
|
http_destroy(http_cli);
|
||||||
};
|
};
|
||||||
http_request(http_cli, etcd_address, req, { .timeout = timeout, .ssl = ssl, .ssl_ca = etcd_ca }, cb);
|
http_request(http_cli, etcd_address, req, { .timeout = timeout, .ssl = ssl }, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void etcd_state_client_t::etcd_call(std::string api, json11::Json payload, int timeout,
|
void etcd_state_client_t::etcd_call(std::string api, json11::Json payload, int timeout,
|
||||||
@@ -168,10 +188,8 @@ void etcd_state_client_t::etcd_call(std::string api, json11::Json payload, int t
|
|||||||
callback(err, data);
|
callback(err, data);
|
||||||
};
|
};
|
||||||
if (!keepalive_client)
|
if (!keepalive_client)
|
||||||
{
|
keepalive_client = http_init(tfd, get_http_ctx());
|
||||||
keepalive_client = http_init(tfd);
|
http_request(keepalive_client, etcd_address, req, { .timeout = timeout, .keepalive = true, .ssl = ssl }, cb);
|
||||||
}
|
|
||||||
http_request(keepalive_client, etcd_address, req, { .timeout = timeout, .keepalive = true, .ssl = ssl, .ssl_ca = etcd_ca }, cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void etcd_state_client_t::add_etcd_url(std::string addr)
|
void etcd_state_client_t::add_etcd_url(std::string addr)
|
||||||
@@ -364,10 +382,10 @@ void etcd_state_client_t::start_etcd_watcher()
|
|||||||
etcd_watch_revision_config, etcd_watch_revision_osd, etcd_watch_revision_pg);
|
etcd_watch_revision_config, etcd_watch_revision_osd, etcd_watch_revision_pg);
|
||||||
}
|
}
|
||||||
if (!etcd_watch_ws)
|
if (!etcd_watch_ws)
|
||||||
etcd_watch_ws = http_init(tfd);
|
etcd_watch_ws = http_init(tfd, get_http_ctx());
|
||||||
else
|
else
|
||||||
http_close(etcd_watch_ws);
|
http_close(etcd_watch_ws);
|
||||||
open_websocket(etcd_watch_ws, etcd_address, etcd_api_path+"/watch", { .timeout = etcd_slow_timeout, .ssl = ssl, .ssl_ca = etcd_ca },
|
open_websocket(etcd_watch_ws, etcd_address, etcd_api_path+"/watch", { .timeout = etcd_slow_timeout, .ssl = ssl },
|
||||||
[this, cur_addr = selected_etcd_address](const http_response_t *msg)
|
[this, cur_addr = selected_etcd_address](const http_response_t *msg)
|
||||||
{
|
{
|
||||||
if (msg->body.length())
|
if (msg->body.length())
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ struct inode_watch_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct http_co_t;
|
struct http_co_t;
|
||||||
|
struct http_context_t;
|
||||||
|
|
||||||
struct __attribute__((visibility("default"))) etcd_state_client_t
|
struct __attribute__((visibility("default"))) etcd_state_client_t
|
||||||
{
|
{
|
||||||
@@ -132,6 +133,7 @@ public:
|
|||||||
int log_level = 0;
|
int log_level = 0;
|
||||||
timerfd_manager_t *tfd = NULL;
|
timerfd_manager_t *tfd = NULL;
|
||||||
|
|
||||||
|
http_context_t *http_ctx = NULL;
|
||||||
http_co_t *etcd_watch_ws = NULL, *keepalive_client = NULL;
|
http_co_t *etcd_watch_ws = NULL, *keepalive_client = NULL;
|
||||||
int etcd_watches_initialised = 0;
|
int etcd_watches_initialised = 0;
|
||||||
uint64_t etcd_watch_revision_config = 0;
|
uint64_t etcd_watch_revision_config = 0;
|
||||||
@@ -164,6 +166,7 @@ public:
|
|||||||
json11::Json::object serialize_inode_cfg(inode_config_t *cfg);
|
json11::Json::object serialize_inode_cfg(inode_config_t *cfg);
|
||||||
etcd_kv_t parse_etcd_kv(const json11::Json & kv_json);
|
etcd_kv_t parse_etcd_kv(const json11::Json & kv_json);
|
||||||
std::vector<std::string> get_addresses();
|
std::vector<std::string> get_addresses();
|
||||||
|
http_context_t *get_http_ctx();
|
||||||
void etcd_call_oneshot(std::string etcd_address, std::string api, json11::Json payload, int timeout, std::function<void(std::string, json11::Json)> callback);
|
void etcd_call_oneshot(std::string etcd_address, std::string api, json11::Json payload, int timeout, std::function<void(std::string, json11::Json)> callback);
|
||||||
void etcd_call(std::string api, json11::Json payload, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
void etcd_call(std::string api, json11::Json payload, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
||||||
void etcd_txn(json11::Json txn, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
void etcd_txn(json11::Json txn, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
||||||
|
|||||||
+63
-37
@@ -34,10 +34,32 @@ static std::string ws_format_frame(int type, uint64_t size);
|
|||||||
static bool ws_parse_frame(std::string & buf, uint8_t & type, std::string & res);
|
static bool ws_parse_frame(std::string & buf, uint8_t & type, std::string & res);
|
||||||
static void parse_http_headers(std::string & res, http_response_t *parsed);
|
static void parse_http_headers(std::string & res, http_response_t *parsed);
|
||||||
|
|
||||||
struct http_co_t
|
struct http_context_t
|
||||||
{
|
{
|
||||||
|
std::string ssl_cert;
|
||||||
|
std::string ssl_key;
|
||||||
|
std::string ssl_ca;
|
||||||
|
|
||||||
#ifdef WITH_OPENSSL
|
#ifdef WITH_OPENSSL
|
||||||
SSL_CTX *ssl_ctx = NULL;
|
SSL_CTX *ssl_ctx = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
~http_context_t()
|
||||||
|
{
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
if (ssl_ctx)
|
||||||
|
{
|
||||||
|
SSL_CTX_free(ssl_ctx);
|
||||||
|
ssl_ctx = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct http_co_t
|
||||||
|
{
|
||||||
|
http_context_t *ctx = NULL;
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
SSL *ssl_cli = NULL;
|
SSL *ssl_cli = NULL;
|
||||||
BIO *ssl_bio = NULL;
|
BIO *ssl_bio = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -47,9 +69,6 @@ struct http_co_t
|
|||||||
|
|
||||||
int request_timeout = 0;
|
int request_timeout = 0;
|
||||||
bool ssl = false;
|
bool ssl = false;
|
||||||
std::string ssl_cert;
|
|
||||||
std::string ssl_key;
|
|
||||||
std::string ssl_ca;
|
|
||||||
std::string host;
|
std::string host;
|
||||||
std::string request;
|
std::string request;
|
||||||
std::string ws_outbox;
|
std::string ws_outbox;
|
||||||
@@ -108,11 +127,47 @@ struct http_co_t
|
|||||||
|
|
||||||
#define DEFAULT_TIMEOUT 5000
|
#define DEFAULT_TIMEOUT 5000
|
||||||
|
|
||||||
http_co_t *http_init(timerfd_manager_t *tfd)
|
http_context_t* http_context_init(const std::string & ssl_cert, const std::string & ssl_key, const std::string & ssl_ca, std::string & error)
|
||||||
|
{
|
||||||
|
http_context_t *ctx = new http_context_t;
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
|
||||||
|
ctx->ssl_cert = ssl_cert;
|
||||||
|
ctx->ssl_key = ssl_key;
|
||||||
|
ctx->ssl_ca = ssl_ca;
|
||||||
|
ctx->ssl_ctx = ssl_ctx;
|
||||||
|
if (!ssl_ctx)
|
||||||
|
goto init_err;
|
||||||
|
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
|
||||||
|
if (!SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_2_VERSION))
|
||||||
|
goto init_err;
|
||||||
|
if ((ssl_ca != "")
|
||||||
|
? !SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca.c_str(), NULL)
|
||||||
|
: !SSL_CTX_set_default_verify_paths(ssl_ctx))
|
||||||
|
goto init_err;
|
||||||
|
if (ssl_cert != "" && ssl_key != "" &&
|
||||||
|
(!SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert.c_str(), SSL_FILETYPE_PEM) ||
|
||||||
|
!SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_key.c_str(), SSL_FILETYPE_PEM)))
|
||||||
|
goto init_err;
|
||||||
|
#endif
|
||||||
|
return ctx;
|
||||||
|
init_err:
|
||||||
|
error = std::string("openssl initialization failed: ")+ERR_error_string(ERR_get_error(), NULL);
|
||||||
|
delete ctx;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_context_destroy(http_context_t *ctx)
|
||||||
|
{
|
||||||
|
delete ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
http_co_t *http_init(timerfd_manager_t *tfd, http_context_t *ctx)
|
||||||
{
|
{
|
||||||
http_co_t *handler = new http_co_t();
|
http_co_t *handler = new http_co_t();
|
||||||
handler->tfd = tfd;
|
handler->tfd = tfd;
|
||||||
handler->state = HTTP_CO_CLOSED;
|
handler->state = HTTP_CO_CLOSED;
|
||||||
|
handler->ctx = ctx;
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +190,6 @@ void open_websocket(http_co_t *handler, const std::string & host, const std::str
|
|||||||
handler->want_streaming = false;
|
handler->want_streaming = false;
|
||||||
handler->keepalive = false;
|
handler->keepalive = false;
|
||||||
handler->ssl = options.ssl;
|
handler->ssl = options.ssl;
|
||||||
handler->ssl_ca = options.ssl_ca;
|
|
||||||
handler->request = request;
|
handler->request = request;
|
||||||
handler->response_callback = response_callback;
|
handler->response_callback = response_callback;
|
||||||
handler->ws_outbox = "";
|
handler->ws_outbox = "";
|
||||||
@@ -188,7 +242,6 @@ void http_co_t::send_request(const std::string & host, const std::string & reque
|
|||||||
this->want_streaming = options.want_streaming;
|
this->want_streaming = options.want_streaming;
|
||||||
this->keepalive = options.keepalive;
|
this->keepalive = options.keepalive;
|
||||||
this->ssl = options.ssl;
|
this->ssl = options.ssl;
|
||||||
this->ssl_ca = options.ssl_ca;
|
|
||||||
this->host = host;
|
this->host = host;
|
||||||
this->request = request;
|
this->request = request;
|
||||||
this->response = "";
|
this->response = "";
|
||||||
@@ -297,13 +350,6 @@ void http_response_t::parse_json_response(std::string & error, json11::Json & r)
|
|||||||
http_co_t::~http_co_t()
|
http_co_t::~http_co_t()
|
||||||
{
|
{
|
||||||
close_connection();
|
close_connection();
|
||||||
#ifdef WITH_OPENSSL
|
|
||||||
if (ssl_ctx)
|
|
||||||
{
|
|
||||||
SSL_CTX_free(ssl_ctx);
|
|
||||||
ssl_ctx = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_co_t::close_connection()
|
void http_co_t::close_connection()
|
||||||
@@ -382,29 +428,14 @@ void http_co_t::start_connection()
|
|||||||
// https://wiki.openssl.org/index.php/Hostname_validation
|
// https://wiki.openssl.org/index.php/Hostname_validation
|
||||||
if (ssl)
|
if (ssl)
|
||||||
{
|
{
|
||||||
if (!ssl_ctx)
|
if (!ctx)
|
||||||
{
|
goto init_err;
|
||||||
ssl_ctx = SSL_CTX_new(TLS_method());
|
|
||||||
if (!ssl_ctx)
|
|
||||||
goto init_err;
|
|
||||||
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
|
|
||||||
if (!SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_2_VERSION))
|
|
||||||
goto init_err;
|
|
||||||
if ((ssl_ca != "")
|
|
||||||
? !SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca.c_str(), NULL)
|
|
||||||
: !SSL_CTX_set_default_verify_paths(ssl_ctx))
|
|
||||||
goto init_err;
|
|
||||||
if (ssl_cert != "" && ssl_key != "" &&
|
|
||||||
(!SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert.c_str(), SSL_FILETYPE_PEM) ||
|
|
||||||
!SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_key.c_str(), SSL_FILETYPE_PEM)))
|
|
||||||
goto init_err;
|
|
||||||
}
|
|
||||||
ssl_bio = BIO_new(BIO_s_socket());
|
ssl_bio = BIO_new(BIO_s_socket());
|
||||||
if (!ssl_bio)
|
if (!ssl_bio)
|
||||||
goto init_err;
|
goto init_err;
|
||||||
if (!BIO_set_fd(ssl_bio, peer_fd, BIO_NOCLOSE))
|
if (!BIO_set_fd(ssl_bio, peer_fd, BIO_NOCLOSE))
|
||||||
goto init_err;
|
goto init_err;
|
||||||
ssl_cli = SSL_new(ssl_ctx);
|
ssl_cli = SSL_new(ctx->ssl_ctx);
|
||||||
if (!ssl_cli)
|
if (!ssl_cli)
|
||||||
goto init_err;
|
goto init_err;
|
||||||
SSL_set_bio(ssl_cli, ssl_bio, ssl_bio);
|
SSL_set_bio(ssl_cli, ssl_bio, ssl_bio);
|
||||||
@@ -421,11 +452,6 @@ init_err:
|
|||||||
BIO_free(ssl_bio);
|
BIO_free(ssl_bio);
|
||||||
ssl_bio = NULL;
|
ssl_bio = NULL;
|
||||||
}
|
}
|
||||||
if (ssl_ctx)
|
|
||||||
{
|
|
||||||
SSL_CTX_free(ssl_ctx);
|
|
||||||
ssl_ctx = NULL;
|
|
||||||
}
|
|
||||||
parsed = { .error = std::string("openssl initialization failed: ")+ERR_error_string(ERR_get_error(), NULL) };
|
parsed = { .error = std::string("openssl initialization failed: ")+ERR_error_string(ERR_get_error(), NULL) };
|
||||||
response_callback(&parsed);
|
response_callback(&parsed);
|
||||||
response_callback = NULL;
|
response_callback = NULL;
|
||||||
|
|||||||
@@ -23,11 +23,10 @@ struct http_options_t
|
|||||||
bool want_streaming;
|
bool want_streaming;
|
||||||
bool keepalive;
|
bool keepalive;
|
||||||
bool ssl;
|
bool ssl;
|
||||||
std::string ssl_cert;
|
|
||||||
std::string ssl_key;
|
|
||||||
std::string ssl_ca;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct http_context_t;
|
||||||
|
|
||||||
struct http_response_t
|
struct http_response_t
|
||||||
{
|
{
|
||||||
std::string error;
|
std::string error;
|
||||||
@@ -45,7 +44,9 @@ struct http_response_t
|
|||||||
// Opened websocket or keepalive HTTP connection
|
// Opened websocket or keepalive HTTP connection
|
||||||
struct http_co_t;
|
struct http_co_t;
|
||||||
|
|
||||||
http_co_t* http_init(timerfd_manager_t *tfd);
|
http_context_t* http_context_init(const std::string & ssl_cert, const std::string & ssl_key, const std::string & ssl_ca, std::string & error);
|
||||||
|
void http_context_destroy(http_context_t *ctx);
|
||||||
|
http_co_t* http_init(timerfd_manager_t *tfd, http_context_t *ctx = NULL);
|
||||||
void open_websocket(http_co_t *handler, const std::string & host, const std::string & path,
|
void open_websocket(http_co_t *handler, const std::string & host, const std::string & path,
|
||||||
const http_options_t & options, std::function<void(const http_response_t *msg)> on_message);
|
const http_options_t & options, std::function<void(const http_response_t *msg)> on_message);
|
||||||
void http_request(http_co_t *handler, const std::string & host, const std::string & request,
|
void http_request(http_co_t *handler, const std::string & host, const std::string & request,
|
||||||
|
|||||||
Reference in New Issue
Block a user