Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

httpserver.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <httpserver.h>
6 
7 #include <init.h>
8 #include <chainparamsbase.h>
9 #include <compat.h>
10 #include <util.h>
11 #include <utilstrencodings.h>
12 #include <netbase.h>
13 #include <rpc/protocol.h> // For HTTP status codes
14 #include <sync.h>
15 #include <ui_interface.h>
16 
17 #include <memory>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <signal.h>
25 
26 #include <event2/thread.h>
27 #include <event2/buffer.h>
28 #include <event2/bufferevent.h>
29 #include <event2/util.h>
30 #include <event2/keyvalq_struct.h>
31 
32 #include <support/events.h>
33 
34 #ifdef EVENT__HAVE_NETINET_IN_H
35 #include <netinet/in.h>
36 #ifdef _XOPEN_SOURCE_EXTENDED
37 #include <arpa/inet.h>
38 #endif
39 #endif
40 
41 #include <thread>
42 #include <mutex>
43 #include <condition_variable>
44 
46 static const size_t MAX_HEADERS_SIZE = 8192;
47 
49 class HTTPWorkItem final : public HTTPClosure
50 {
51 public:
52  HTTPWorkItem(std::unique_ptr<HTTPRequest> _req, const std::string &_path, const HTTPRequestHandler& _func):
53  req(std::move(_req)), path(_path), func(_func)
54  {
55  }
56  void operator()() override
57  {
58  func(req.get(), path);
59  }
60 
61  std::unique_ptr<HTTPRequest> req;
62 
63 private:
64  std::string path;
66 };
67 
71 template <typename WorkItem>
72 class WorkQueue
73 {
74 private:
76  std::mutex cs;
77  std::condition_variable cond;
78  std::deque<std::unique_ptr<WorkItem>> queue;
79  bool running;
80  size_t maxDepth;
81 
82 public:
83  explicit WorkQueue(size_t _maxDepth) : running(true),
84  maxDepth(_maxDepth)
85  {
86  }
90  {
91  }
93  bool Enqueue(WorkItem* item)
94  {
95  std::unique_lock<std::mutex> lock(cs);
96  if (queue.size() >= maxDepth) {
97  return false;
98  }
99  queue.emplace_back(std::unique_ptr<WorkItem>(item));
100  cond.notify_one();
101  return true;
102  }
104  void Run()
105  {
106  while (true) {
107  std::unique_ptr<WorkItem> i;
108  {
109  std::unique_lock<std::mutex> lock(cs);
110  while (running && queue.empty())
111  cond.wait(lock);
112  if (!running)
113  break;
114  i = std::move(queue.front());
115  queue.pop_front();
116  }
117  (*i)();
118  }
119  }
121  void Interrupt()
122  {
123  std::unique_lock<std::mutex> lock(cs);
124  running = false;
125  cond.notify_all();
126  }
127 };
128 
130 {
132  HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler):
133  prefix(_prefix), exactMatch(_exactMatch), handler(_handler)
134  {
135  }
136  std::string prefix;
139 };
140 
143 static struct event_base* eventBase = nullptr;
146 struct evhttp* eventHTTP = nullptr;
148 static std::vector<CSubNet> rpc_allow_subnets;
152 std::vector<HTTPPathHandler> pathHandlers;
154 std::vector<evhttp_bound_socket *> boundSockets;
155 
157 static bool ClientAllowed(const CNetAddr& netaddr)
158 {
159  if (!netaddr.IsValid())
160  return false;
161  for(const CSubNet& subnet : rpc_allow_subnets)
162  if (subnet.Match(netaddr))
163  return true;
164  return false;
165 }
166 
168 static bool InitHTTPAllowList()
169 {
170  rpc_allow_subnets.clear();
171  CNetAddr localv4;
172  CNetAddr localv6;
173  LookupHost("127.0.0.1", localv4, false);
174  LookupHost("::1", localv6, false);
175  rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
176  rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
177  for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) {
178  CSubNet subnet;
179  LookupSubNet(strAllow.c_str(), subnet);
180  if (!subnet.IsValid()) {
182  strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
184  return false;
185  }
186  rpc_allow_subnets.push_back(subnet);
187  }
188  std::string strAllowed;
189  for (const CSubNet& subnet : rpc_allow_subnets)
190  strAllowed += subnet.ToString() + " ";
191  LogPrint(BCLog::HTTP, "Allowing HTTP connections from: %s\n", strAllowed);
192  return true;
193 }
194 
197 {
198  switch (m) {
199  case HTTPRequest::GET:
200  return "GET";
201  break;
202  case HTTPRequest::POST:
203  return "POST";
204  break;
205  case HTTPRequest::HEAD:
206  return "HEAD";
207  break;
208  case HTTPRequest::PUT:
209  return "PUT";
210  break;
211  default:
212  return "unknown";
213  }
214 }
215 
217 static void http_request_cb(struct evhttp_request* req, void* arg)
218 {
219  // Disable reading to work around a libevent bug, fixed in 2.2.0.
220  if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
221  evhttp_connection* conn = evhttp_request_get_connection(req);
222  if (conn) {
223  bufferevent* bev = evhttp_connection_get_bufferevent(conn);
224  if (bev) {
225  bufferevent_disable(bev, EV_READ);
226  }
227  }
228  }
229  std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
230 
231  LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
232  RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
233 
234  // Early address-based allow check
235  if (!ClientAllowed(hreq->GetPeer())) {
236  hreq->WriteReply(HTTP_FORBIDDEN);
237  return;
238  }
239 
240  // Early reject unknown HTTP methods
241  if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
242  hreq->WriteReply(HTTP_BADMETHOD);
243  return;
244  }
245 
246  // Find registered handler for prefix
247  std::string strURI = hreq->GetURI();
248  std::string path;
249  std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin();
250  std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end();
251  for (; i != iend; ++i) {
252  bool match = false;
253  if (i->exactMatch)
254  match = (strURI == i->prefix);
255  else
256  match = (strURI.substr(0, i->prefix.size()) == i->prefix);
257  if (match) {
258  path = strURI.substr(i->prefix.size());
259  break;
260  }
261  }
262 
263  // Dispatch to worker thread
264  if (i != iend) {
265  std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(std::move(hreq), path, i->handler));
266  assert(workQueue);
267  if (workQueue->Enqueue(item.get()))
268  item.release(); /* if true, queue took ownership */
269  else {
270  LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n");
271  item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
272  }
273  } else {
274  hreq->WriteReply(HTTP_NOTFOUND);
275  }
276 }
277 
279 static void http_reject_request_cb(struct evhttp_request* req, void*)
280 {
281  LogPrint(BCLog::HTTP, "Rejecting request while shutting down\n");
282  evhttp_send_error(req, HTTP_SERVUNAVAIL, nullptr);
283 }
284 
286 static bool ThreadHTTP(struct event_base* base, struct evhttp* http)
287 {
288  RenameThread("dash-http");
289  LogPrint(BCLog::HTTP, "Entering http event loop\n");
290  event_base_dispatch(base);
291  // Event loop will be interrupted by InterruptHTTPServer()
292  LogPrint(BCLog::HTTP, "Exited http event loop\n");
293  return event_base_got_break(base) == 0;
294 }
295 
297 static bool HTTPBindAddresses(struct evhttp* http)
298 {
299  int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
300  std::vector<std::pair<std::string, uint16_t> > endpoints;
301 
302  // Determine what addresses to bind to
303  if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs
304  endpoints.push_back(std::make_pair("::1", defaultPort));
305  endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
306  if (gArgs.IsArgSet("-rpcbind")) {
307  LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
308  }
309  } else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
310  for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
311  int port = defaultPort;
312  std::string host;
313  SplitHostPort(strRPCBind, port, host);
314  endpoints.push_back(std::make_pair(host, port));
315  }
316  } else { // No specific bind address specified, bind to any
317  endpoints.push_back(std::make_pair("::", defaultPort));
318  endpoints.push_back(std::make_pair("0.0.0.0", defaultPort));
319  }
320 
321  // Bind addresses
322  for (std::vector<std::pair<std::string, uint16_t> >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) {
323  LogPrint(BCLog::HTTP, "Binding RPC on address %s port %i\n", i->first, i->second);
324  evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second);
325  if (bind_handle) {
326  boundSockets.push_back(bind_handle);
327  } else {
328  LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);
329  }
330  }
331  return !boundSockets.empty();
332 }
333 
336 {
337  RenameThread("dash-httpworker");
338  queue->Run();
339 }
340 
342 static void libevent_log_cb(int severity, const char *msg)
343 {
344 #ifndef EVENT_LOG_WARN
345 // EVENT_LOG_WARN was added in 2.0.19; but before then _EVENT_LOG_WARN existed.
346 # define EVENT_LOG_WARN _EVENT_LOG_WARN
347 #endif
348  if (severity >= EVENT_LOG_WARN) // Log warn messages and higher without debug category
349  LogPrintf("libevent: %s\n", msg);
350  // The below code causes log spam on Travis and the output of these logs has never been of any use so far
351  //else
352  // LogPrint(BCLog::LIBEVENT, "libevent: %s\n", msg);
353 }
354 
356 {
357  if (!InitHTTPAllowList())
358  return false;
359 
360  if (gArgs.GetBoolArg("-rpcssl", false)) {
362  "SSL mode for RPC (-rpcssl) is no longer supported.",
364  return false;
365  }
366 
367  // Redirect libevent's logging to our own log
368  event_set_log_callback(&libevent_log_cb);
369  // Update libevent's log handling. Returns false if our version of
370  // libevent doesn't support debug logging, in which case we should
371  // clear the BCLog::LIBEVENT flag.
374  }
375 
376 #ifdef WIN32
377  evthread_use_windows_threads();
378 #else
379  evthread_use_pthreads();
380 #endif
381 
382  raii_event_base base_ctr = obtain_event_base();
383 
384  /* Create a new evhttp object to handle requests. */
385  raii_evhttp http_ctr = obtain_evhttp(base_ctr.get());
386  struct evhttp* http = http_ctr.get();
387  if (!http) {
388  LogPrintf("couldn't create evhttp. Exiting.\n");
389  return false;
390  }
391 
392  evhttp_set_timeout(http, gArgs.GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT));
393  evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE);
394  evhttp_set_max_body_size(http, MAX_SIZE);
395  evhttp_set_gencb(http, http_request_cb, nullptr);
396 
397  if (!HTTPBindAddresses(http)) {
398  LogPrintf("Unable to bind any endpoint for RPC server\n");
399  return false;
400  }
401 
402  LogPrint(BCLog::HTTP, "Initialized HTTP server\n");
403  int workQueueDepth = std::max((long)gArgs.GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
404  LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);
405 
406  workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
407  // transfer ownership to eventBase/HTTP via .release()
408  eventBase = base_ctr.release();
409  eventHTTP = http_ctr.release();
410  return true;
411 }
412 
413 bool UpdateHTTPServerLogging(bool enable) {
414 #if LIBEVENT_VERSION_NUMBER >= 0x02010100
415  if (enable) {
416  event_enable_debug_logging(EVENT_DBG_ALL);
417  } else {
418  event_enable_debug_logging(EVENT_DBG_NONE);
419  }
420  return true;
421 #else
422  // Can't update libevent logging if version < 02010100
423  return false;
424 #endif
425 }
426 
427 std::thread threadHTTP;
428 static std::vector<std::thread> g_thread_http_workers;
429 
431 {
432  LogPrint(BCLog::HTTP, "Starting HTTP server\n");
433  int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
434  LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
435  threadHTTP = std::thread(ThreadHTTP, eventBase, eventHTTP);
436 
437  for (int i = 0; i < rpcThreads; i++) {
439  }
440  return true;
441 }
442 
444 {
445  LogPrint(BCLog::HTTP, "Interrupting HTTP server\n");
446  if (eventHTTP) {
447  // Reject requests on current connections
448  evhttp_set_gencb(eventHTTP, http_reject_request_cb, nullptr);
449  }
450  if (workQueue)
451  workQueue->Interrupt();
452 }
453 
455 {
456  LogPrint(BCLog::HTTP, "Stopping HTTP server\n");
457  if (workQueue) {
458  LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
459  for (auto& thread: g_thread_http_workers) {
460  thread.join();
461  }
462  g_thread_http_workers.clear();
463  delete workQueue;
464  workQueue = nullptr;
465  }
466  // Unlisten sockets, these are what make the event loop running, which means
467  // that after this and all connections are closed the event loop will quit.
468  for (evhttp_bound_socket *socket : boundSockets) {
469  evhttp_del_accept_socket(eventHTTP, socket);
470  }
471  boundSockets.clear();
472  if (eventBase) {
473  LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n");
474  threadHTTP.join();
475  }
476  if (eventHTTP) {
477  evhttp_free(eventHTTP);
478  eventHTTP = nullptr;
479  }
480  if (eventBase) {
481  event_base_free(eventBase);
482  eventBase = nullptr;
483  }
484  LogPrint(BCLog::HTTP, "Stopped HTTP server\n");
485 }
486 
487 struct event_base* EventBase()
488 {
489  return eventBase;
490 }
491 
492 static void httpevent_callback_fn(evutil_socket_t, short, void* data)
493 {
494  // Static handler: simply call inner handler
495  HTTPEvent *self = ((HTTPEvent*)data);
496  self->handler();
497  if (self->deleteWhenTriggered)
498  delete self;
499 }
500 
501 HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function<void(void)>& _handler):
502  deleteWhenTriggered(_deleteWhenTriggered), handler(_handler)
503 {
504  ev = event_new(base, -1, 0, httpevent_callback_fn, this);
505  assert(ev);
506 }
508 {
509  event_free(ev);
510 }
511 void HTTPEvent::trigger(struct timeval* tv)
512 {
513  if (tv == nullptr)
514  event_active(ev, 0, 0); // immediately trigger event in main thread
515  else
516  evtimer_add(ev, tv); // trigger after timeval passed
517 }
518 HTTPRequest::HTTPRequest(struct evhttp_request* _req) : req(_req),
519  replySent(false)
520 {
521 }
523 {
524  if (!replySent) {
525  // Keep track of whether reply was sent to avoid request leaks
526  LogPrintf("%s: Unhandled request\n", __func__);
527  WriteReply(HTTP_INTERNAL, "Unhandled request");
528  }
529  // evhttpd cleans up the request, as long as a reply was sent.
530 }
531 
532 std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
533 {
534  const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
535  assert(headers);
536  const char* val = evhttp_find_header(headers, hdr.c_str());
537  if (val)
538  return std::make_pair(true, val);
539  else
540  return std::make_pair(false, "");
541 }
542 
544 {
545  struct evbuffer* buf = evhttp_request_get_input_buffer(req);
546  if (!buf)
547  return "";
548  size_t size = evbuffer_get_length(buf);
555  const char* data = (const char*)evbuffer_pullup(buf, size);
556  if (!data) // returns nullptr in case of empty buffer
557  return "";
558  std::string rv(data, size);
559  evbuffer_drain(buf, size);
560  return rv;
561 }
562 
563 void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value)
564 {
565  struct evkeyvalq* headers = evhttp_request_get_output_headers(req);
566  assert(headers);
567  evhttp_add_header(headers, hdr.c_str(), value.c_str());
568 }
569 
575 void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
576 {
577  assert(!replySent && req);
578  if (ShutdownRequested()) {
579  WriteHeader("Connection", "close");
580  }
581  // Send event to main http thread to send reply message
582  struct evbuffer* evb = evhttp_request_get_output_buffer(req);
583  assert(evb);
584  evbuffer_add(evb, strReply.data(), strReply.size());
585  auto req_copy = req;
586  HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{
587  evhttp_send_reply(req_copy, nStatus, nullptr, nullptr);
588  // Re-enable reading from the socket. This is the second part of the libevent
589  // workaround above.
590  if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
591  evhttp_connection* conn = evhttp_request_get_connection(req_copy);
592  if (conn) {
593  bufferevent* bev = evhttp_connection_get_bufferevent(conn);
594  if (bev) {
595  bufferevent_enable(bev, EV_READ | EV_WRITE);
596  }
597  }
598  }
599  });
600  ev->trigger(nullptr);
601  replySent = true;
602  req = nullptr; // transferred back to main thread
603 }
604 
606 {
607  evhttp_connection* con = evhttp_request_get_connection(req);
608  CService peer;
609  if (con) {
610  // evhttp retains ownership over returned address string
611  const char* address = "";
612  uint16_t port = 0;
613  evhttp_connection_get_peer(con, (char**)&address, &port);
614  peer = LookupNumeric(address, port);
615  }
616  return peer;
617 }
618 
619 std::string HTTPRequest::GetURI()
620 {
621  return evhttp_request_get_uri(req);
622 }
623 
625 {
626  switch (evhttp_request_get_command(req)) {
627  case EVHTTP_REQ_GET:
628  return GET;
629  break;
630  case EVHTTP_REQ_POST:
631  return POST;
632  break;
633  case EVHTTP_REQ_HEAD:
634  return HEAD;
635  break;
636  case EVHTTP_REQ_PUT:
637  return PUT;
638  break;
639  default:
640  return UNKNOWN;
641  break;
642  }
643 }
644 
645 void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
646 {
647  LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
648  pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
649 }
650 
651 void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
652 {
653  std::vector<HTTPPathHandler>::iterator i = pathHandlers.begin();
654  std::vector<HTTPPathHandler>::iterator iend = pathHandlers.end();
655  for (; i != iend; ++i)
656  if (i->prefix == prefix && i->exactMatch == exactMatch)
657  break;
658  if (i != iend)
659  {
660  LogPrint(BCLog::HTTP, "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
661  pathHandlers.erase(i);
662  }
663 }
664 
665 std::string urlDecode(const std::string &urlEncoded) {
666  std::string res;
667  if (!urlEncoded.empty()) {
668  char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
669  if (decoded) {
670  res = std::string(decoded);
671  free(decoded);
672  }
673  }
674  return res;
675 }
bool(* handler)(HTTPRequest *req, const std::string &strReq)
Definition: rest.cpp:575
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: util.cpp:784
raii_event_base obtain_event_base()
Definition: events.h:30
std::vector< evhttp_bound_socket * > boundSockets
Bound listening sockets.
Definition: httpserver.cpp:154
bool StartHTTPServer()
Start HTTP server.
Definition: httpserver.cpp:430
static const int DEFAULT_HTTP_SERVER_TIMEOUT
Definition: httpserver.h:14
HTTPWorkItem(std::unique_ptr< HTTPRequest > _req, const std::string &_path, const HTTPRequestHandler &_func)
Definition: httpserver.cpp:52
HTTPRequest(struct evhttp_request *req)
Definition: httpserver.cpp:518
raii_evhttp obtain_evhttp(struct event_base *base)
Definition: events.h:41
Definition: util.h:107
bool ShutdownRequested()
Definition: init.cpp:179
#define strprintf
Definition: tinyformat.h:1066
static const int DEFAULT_HTTP_WORKQUEUE
Definition: httpserver.h:13
std::vector< HTTPPathHandler > pathHandlers
Handlers for (sub)paths.
Definition: httpserver.cpp:152
std::pair< bool, std::string > GetHeader(const std::string &hdr)
Get the request header specified by hdr, or an empty string.
Definition: httpserver.cpp:532
CService LookupNumeric(const char *pszName, int portDefault)
Definition: netbase.cpp:168
Event class.
Definition: httpserver.h:130
const char * prefix
Definition: rest.cpp:574
std::string urlDecode(const std::string &urlEncoded)
Definition: httpserver.cpp:665
std::string GetURI()
Get requested URI.
Definition: httpserver.cpp:619
static void httpevent_callback_fn(evutil_socket_t, short, void *data)
Definition: httpserver.cpp:492
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
static std::vector< CSubNet > rpc_allow_subnets
List of subnets to allow RPC connections from.
Definition: httpserver.cpp:148
Definition: box.hpp:161
size_t maxDepth
Definition: httpserver.cpp:80
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
Definition: httpserver.cpp:342
false true true true
Definition: bls_dkg.cpp:176
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: util.cpp:824
std::string path
Definition: httpserver.cpp:64
struct evhttp_request * req
Definition: httpserver.h:60
std::deque< std::unique_ptr< WorkItem > > queue
Definition: httpserver.cpp:78
std::thread threadHTTP
Definition: httpserver.cpp:427
static bool InitHTTPAllowList()
Initialize ACL list for HTTP server.
Definition: httpserver.cpp:168
HTTP request work item.
Definition: httpserver.cpp:49
void InterruptHTTPServer()
Interrupt HTTP server threads.
Definition: httpserver.cpp:443
RequestMethod GetRequestMethod()
Get request method.
Definition: httpserver.cpp:624
void RenameThread(const char *name)
Definition: util.cpp:1244
bool Enqueue(WorkItem *item)
Enqueue a work item.
Definition: httpserver.cpp:93
Event handler closure.
Definition: httpserver.h:121
struct event * ev
Definition: httpserver.h:148
static bool HTTPBindAddresses(struct evhttp *http)
Bind HTTP server to specified addresses.
Definition: httpserver.cpp:297
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
Definition: httpserver.cpp:645
#define L(x0, x1, x2, x3, x4, x5, x6, x7)
Definition: jh.c:501
bool IsValid() const
Definition: netaddress.cpp:191
static std::string RequestMethodString(HTTPRequest::RequestMethod m)
HTTP request method as string - use for logging only.
Definition: httpserver.cpp:196
void Run()
Thread function.
Definition: httpserver.cpp:104
static bool ThreadHTTP(struct event_base *base, struct evhttp *http)
Event dispatcher thread.
Definition: httpserver.cpp:286
false
Definition: bls_dkg.cpp:168
HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler)
Definition: httpserver.cpp:132
static void http_reject_request_cb(struct evhttp_request *req, void *)
Callback to reject HTTP requests after shutdown.
Definition: httpserver.cpp:279
bool InitHTTPServer()
Initialize HTTP server.
Definition: httpserver.cpp:355
#define LogPrintf(...)
Definition: util.h:203
void StopHTTPServer()
Stop HTTP server.
Definition: httpserver.cpp:454
void WriteReply(int nStatus, const std::string &strReply="")
Write HTTP reply.
Definition: httpserver.cpp:575
std::atomic< uint64_t > logCategories
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:143
std::condition_variable cond
Definition: httpserver.cpp:77
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
Definition: httpserver.cpp:651
HTTPRequestHandler func
Definition: httpserver.cpp:65
std::function< void(void)> handler
Definition: httpserver.h:146
std::mutex cs
Mutex protects entire object.
Definition: httpserver.cpp:76
CService GetPeer()
Get CService (address:ip) for the origin of the http request.
Definition: httpserver.cpp:605
struct event_base * EventBase()
Return evhttp event base.
Definition: httpserver.cpp:487
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:618
static bool ClientAllowed(const CNetAddr &netaddr)
Check if a network address is allowed to access the HTTP server.
Definition: httpserver.cpp:157
#define LogPrint(category,...)
Definition: util.h:214
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:33
bool IsValid() const
Definition: netaddress.cpp:711
Simple work queue for distributing work over multiple threads.
Definition: httpserver.cpp:72
static WorkQueue< HTTPClosure > * workQueue
Work queue for handling longer requests off the event loop thread.
Definition: httpserver.cpp:150
ArgsManager gArgs
Definition: util.cpp:108
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
#define EVENT_LOG_WARN
std::string prefix
Definition: httpserver.cpp:136
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
Definition: httpserver.cpp:563
static const unsigned int MAX_SIZE
Definition: serialize.h:29
void trigger(struct timeval *tv)
Trigger the event.
Definition: httpserver.cpp:511
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:808
static void HTTPWorkQueueRun(WorkQueue< HTTPClosure > *queue)
Simple wrapper to set thread name and run work queue.
Definition: httpserver.cpp:335
HTTPEvent(struct event_base *base, bool deleteWhenTriggered, const std::function< void(void)> &handler)
Create a new event.
Definition: httpserver.cpp:501
bool running
Definition: httpserver.cpp:79
std::function< bool(HTTPRequest *req, const std::string &)> HTTPRequestHandler
Handler for requests to a certain HTTP path.
Definition: httpserver.h:40
static const size_t MAX_HEADERS_SIZE
Maximum size of http request (request line + headers)
Definition: httpserver.cpp:46
static void http_request_cb(struct evhttp_request *req, void *arg)
HTTP request callback.
Definition: httpserver.cpp:217
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Show message box.
Definition: ui_interface.h:76
void operator()() override
Definition: httpserver.cpp:56
std::string ReadBody()
Read request body.
Definition: httpserver.cpp:543
WorkQueue(size_t _maxDepth)
Definition: httpserver.cpp:83
In-flight HTTP request.
Definition: httpserver.h:57
std::unique_ptr< HTTPRequest > req
Definition: httpserver.cpp:61
CClientUIInterface uiInterface
Definition: ui_interface.cpp:8
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:117
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: util.cpp:765
HTTPRequestHandler handler
Definition: httpserver.cpp:138
static std::vector< std::thread > g_thread_http_workers
Definition: httpserver.cpp:428
bool replySent
Definition: httpserver.h:61
struct evhttp * eventHTTP
HTTP server.
Definition: httpserver.cpp:146
static const int DEFAULT_HTTP_THREADS
Definition: httpserver.h:12
bool UpdateHTTPServerLogging(bool enable)
Change logging level for libevent.
Definition: httpserver.cpp:413
static struct event_base * eventBase
HTTP module state.
Definition: httpserver.cpp:144
~WorkQueue()
Precondition: worker threads have all stopped (they have been joined).
Definition: httpserver.cpp:89
void Interrupt()
Interrupt and exit loops.
Definition: httpserver.cpp:121
Released under the MIT license