Prefer local etcd addresses and correctly cycle over them even when they need resolving

Seems slightly overcomplicated...
This commit is contained in:
Vitaliy Filippov
2026-04-22 01:41:29 +03:00
parent 800744b5c3
commit 08401808e8
5 changed files with 243 additions and 119 deletions
+43 -4
View File
@@ -199,6 +199,45 @@ init_err:
return NULL;
}
struct http_ctx_resolve_t
{
std::function<void(const std::string & error, const std::vector<std::string> & addrs)> cb;
};
void http_resolve_ares_cb(void *data, int status, int timeouts, struct ares_addrinfo *result)
{
http_ctx_resolve_t *obj = (http_ctx_resolve_t*)data;
if (status != ARES_SUCCESS)
{
obj->cb(ares_strerror(status), {});
delete obj;
return;
}
std::vector<std::string> addrs;
for (auto node = result->nodes; node; node = node->ai_next)
{
sockaddr_storage ss;
memset(&ss, 0, sizeof(ss));
memcpy(&ss, node->ai_addr, node->ai_addrlen);
addrs.push_back(addr_to_string(ss));
}
obj->cb("", addrs);
delete obj;
}
void http_resolve(http_context_t *ctx, bool ssl, std::string host,
std::function<void(const std::string & error, const std::vector<std::string> & addrs)> cb)
{
auto obj = new http_ctx_resolve_t();
obj->cb = std::move(cb);
ares_addrinfo_hints hints = { .ai_flags = ARES_AI_NOSORT|ARES_AI_NUMERICSERV };
auto pos = host.rfind(':');
if (pos != std::string::npos)
host[pos] = 0;
ares_getaddrinfo(ctx->ares, host.c_str(),
pos != std::string::npos ? host.c_str()+pos+1 : (ssl ? "443" : "80"), &hints, http_resolve_ares_cb, obj);
}
void http_context_destroy(http_context_t *ctx)
{
delete ctx;
@@ -213,21 +252,21 @@ http_co_t *http_init(http_context_t *ctx)
return handler;
}
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 & addr, const std::string & hostname, const std::string & path,
const http_options_t & options, std::function<void(http_message_t *msg)> response_callback)
{
if (handler->state == HTTP_CO_KEEPALIVE && (handler->connected_host != host || handler->ssl != options.ssl))
if (handler->state == HTTP_CO_KEEPALIVE && (handler->connected_host != addr || handler->ssl != options.ssl))
handler->close_connection();
if (handler->state != HTTP_CO_KEEPALIVE && handler->state != HTTP_CO_CLOSED)
throw std::runtime_error("Attempt to open websocket on a keepalive stream");
std::string request = "GET "+path+" HTTP/1.1\r\n"
"Host: "+host+"\r\n"
"Host: "+hostname+"\r\n"
"Upgrade: websocket\r\n"
"Connection: upgrade\r\n"
"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
"Sec-WebSocket-Version: 13\r\n"
"\r\n";
handler->host = host;
handler->host = addr;
handler->host_port = "";
handler->request_timeout = options.timeout < 0 ? -1 : (options.timeout == 0 ? DEFAULT_TIMEOUT : options.timeout);
handler->want_streaming = false;