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