From 2ca645c2e4da0b1b2e792520cf4c1949301e4ae9 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Wed, 15 Jan 2025 14:26:36 -0500 Subject: [PATCH] refactor: split HTTPBindAddresses into config parse and libevent setup The original function was already naturally split into two chunks: First, we parse and validate the users' RPC configuration for IPs and ports. Next we bind libevent's http server to the appropriate endpoints. This commit splits these chunks into two separate functions, leaving the argument parsing in the common space of the module and moving the libevent-specific binding into the http_libevent namespace. A future commit will implement http_bitcoin::HTTPBindAddresses to bind the validate list of endpoints by the new HTTP server. --- src/httpserver.cpp | 54 +++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 9587a99b29e..e912e854227 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -322,8 +322,7 @@ static void ThreadHTTP(struct event_base* base) LogDebug(BCLog::HTTP, "Exited http event loop\n"); } -/** Bind HTTP server to specified addresses */ -static bool HTTPBindAddresses(struct evhttp* http) +static std::vector> GetBindAddresses() { uint16_t http_port{static_cast(gArgs.GetIntArg("-rpcport", BaseParams().RPCPort()))}; std::vector> endpoints; @@ -348,33 +347,12 @@ static bool HTTPBindAddresses(struct evhttp* http) std::string host; if (!SplitHostPort(strRPCBind, port, host)) { LogError("%s\n", InvalidPortErrMsg("-rpcbind", strRPCBind).original); - return false; + return {}; // empty } endpoints.emplace_back(host, port); } } - - // Bind addresses - for (std::vector >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) { - LogInfo("Binding RPC on address %s port %i", i->first, i->second); - evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second); - if (bind_handle) { - const std::optional addr{LookupHost(i->first, false)}; - if (i->first.empty() || (addr.has_value() && addr->IsBindAny())) { - LogWarning("The RPC server is not safe to expose to untrusted networks such as the public internet"); - } - // Set the no-delay option (disable Nagle's algorithm) on the TCP socket. - evutil_socket_t fd = evhttp_bound_socket_get_fd(bind_handle); - int one = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&one), sizeof(one)) == SOCKET_ERROR) { - LogInfo("WARNING: Unable to set TCP_NODELAY on RPC server socket, continuing anyway\n"); - } - boundSockets.push_back(bind_handle); - } else { - LogWarning("Binding RPC on address %s port %i failed.", i->first, i->second); - } - } - return !boundSockets.empty(); + return endpoints; } /** libevent event log callback */ @@ -397,6 +375,32 @@ static void libevent_log_cb(int severity, const char *msg) } namespace http_libevent { +/** Bind HTTP server to specified addresses */ +static bool HTTPBindAddresses(struct evhttp* http) +{ + std::vector> endpoints{GetBindAddresses()}; + for (std::vector >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) { + LogInfo("Binding RPC on address %s port %i", i->first, i->second); + evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second); + if (bind_handle) { + const std::optional addr{LookupHost(i->first, false)}; + if (i->first.empty() || (addr.has_value() && addr->IsBindAny())) { + LogWarning("The RPC server is not safe to expose to untrusted networks such as the public internet"); + } + // Set the no-delay option (disable Nagle's algorithm) on the TCP socket. + evutil_socket_t fd = evhttp_bound_socket_get_fd(bind_handle); + int one = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&one), sizeof(one)) == SOCKET_ERROR) { + LogInfo("WARNING: Unable to set TCP_NODELAY on RPC server socket, continuing anyway"); + } + boundSockets.push_back(bind_handle); + } else { + LogWarning("Binding RPC on address %s port %i failed.", i->first, i->second); + } + } + return !boundSockets.empty(); +} + bool InitHTTPServer(const util::SignalInterrupt& interrupt) { if (!InitHTTPAllowList())