@@ -155,6 +155,8 @@ static std::vector<CSubNet> rpc_allow_subnets;
155155static WorkQueue<HTTPClosure>* workQueue = 0 ;
156156// ! Handlers for (sub)paths
157157std::vector<HTTPPathHandler> pathHandlers;
158+ // ! Bound listening sockets
159+ std::vector<evhttp_bound_socket *> boundSockets;
158160
159161/* * Check if a network address is allowed to access the HTTP server */
160162static bool ClientAllowed (const CNetAddr& netaddr)
@@ -264,6 +266,13 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
264266 }
265267}
266268
269+ /* * Callback to reject HTTP requests after shutdown. */
270+ static void http_reject_request_cb (struct evhttp_request * req, void *)
271+ {
272+ LogPrint (" http" , " Rejecting request while shutting down\n " );
273+ evhttp_send_error (req, HTTP_SERVUNAVAIL, NULL );
274+ }
275+
267276/* * Event dispatcher thread */
268277static void ThreadHTTP (struct event_base * base, struct evhttp * http)
269278{
@@ -278,7 +287,6 @@ static void ThreadHTTP(struct event_base* base, struct evhttp* http)
278287static bool HTTPBindAddresses (struct evhttp * http)
279288{
280289 int defaultPort = GetArg (" -rpcport" , BaseParams ().RPCPort ());
281- int nBound = 0 ;
282290 std::vector<std::pair<std::string, uint16_t > > endpoints;
283291
284292 // Determine what addresses to bind to
@@ -304,13 +312,14 @@ static bool HTTPBindAddresses(struct evhttp* http)
304312 // Bind addresses
305313 for (std::vector<std::pair<std::string, uint16_t > >::iterator i = endpoints.begin (); i != endpoints.end (); ++i) {
306314 LogPrint (" http" , " Binding RPC on address %s port %i\n " , i->first , i->second );
307- if (evhttp_bind_socket (http, i->first .empty () ? NULL : i->first .c_str (), i->second ) == 0 ) {
308- nBound += 1 ;
315+ evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle (http, i->first .empty () ? NULL : i->first .c_str (), i->second );
316+ if (bind_handle) {
317+ boundSockets.push_back (bind_handle);
309318 } else {
310319 LogPrintf (" Binding RPC on address %s port %i failed.\n " , i->first , i->second );
311320 }
312321 }
313- return nBound > 0 ;
322+ return !boundSockets. empty () ;
314323}
315324
316325/* * Simple wrapper to set thread name and run work queue */
@@ -410,8 +419,14 @@ bool StartHTTPServer(boost::thread_group& threadGroup)
410419void InterruptHTTPServer ()
411420{
412421 LogPrint (" http" , " Interrupting HTTP server\n " );
413- if (eventBase)
414- event_base_loopbreak (eventBase);
422+ if (eventHTTP) {
423+ // Unlisten sockets
424+ BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) {
425+ evhttp_del_accept_socket (eventHTTP, socket);
426+ }
427+ // Reject requests on current connections
428+ evhttp_set_gencb (eventHTTP, http_reject_request_cb, NULL );
429+ }
415430 if (workQueue)
416431 workQueue->Interrupt ();
417432}
0 commit comments