Dash Core  0.12.2.1
P2P Digital Currency
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 "chainparamsbase.h"
8 #include "compat.h"
9 #include "util.h"
10 #include "netbase.h"
11 #include "rpc/protocol.h" // For HTTP status codes
12 #include "sync.h"
13 #include "ui_interface.h"
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <signal.h>
22 
23 #include <event2/event.h>
24 #include <event2/http.h>
25 #include <event2/thread.h>
26 #include <event2/buffer.h>
27 #include <event2/util.h>
28 #include <event2/keyvalq_struct.h>
29 
30 #ifdef EVENT__HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #ifdef _XOPEN_SOURCE_EXTENDED
33 #include <arpa/inet.h>
34 #endif
35 #endif
36 
37 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
38 #include <boost/foreach.hpp>
39 #include <boost/scoped_ptr.hpp>
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  boost::scoped_ptr<HTTPRequest> req;
58 
59 private:
60  std::string path;
62 };
63 
67 template <typename WorkItem>
68 class WorkQueue
69 {
70 private:
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;
79 
82  {
83  public:
86  {
87  boost::lock_guard<boost::mutex> lock(wq.cs);
88  wq.numThreads += 1;
89  }
91  {
92  boost::lock_guard<boost::mutex> lock(wq.cs);
93  wq.numThreads -= 1;
94  wq.cond.notify_all();
95  }
96  };
97 
98 public:
99  WorkQueue(size_t maxDepth) : running(true),
101  numThreads(0)
102  {
103  }
104  /*( Precondition: worker threads have all stopped
105  * (call WaitExit)
106  */
108  {
109  while (!queue.empty()) {
110  delete queue.front();
111  queue.pop_front();
112  }
113  }
115  bool Enqueue(WorkItem* item)
116  {
117  boost::unique_lock<boost::mutex> lock(cs);
118  if (queue.size() >= maxDepth) {
119  return false;
120  }
121  queue.push_back(item);
122  cond.notify_one();
123  return true;
124  }
126  void Run()
127  {
128  ThreadCounter count(*this);
129  while (true) {
130  WorkItem* i = 0;
131  {
132  boost::unique_lock<boost::mutex> lock(cs);
133  while (running && queue.empty())
134  cond.wait(lock);
135  if (!running)
136  break;
137  i = queue.front();
138  queue.pop_front();
139  }
140  (*i)();
141  delete i;
142  }
143  }
145  void Interrupt()
146  {
147  boost::unique_lock<boost::mutex> lock(cs);
148  running = false;
149  cond.notify_all();
150  }
152  void WaitExit()
153  {
154  boost::unique_lock<boost::mutex> lock(cs);
155  while (numThreads > 0){
156  cond.wait(lock);
157  }
158  }
159 
161  size_t Depth()
162  {
163  boost::unique_lock<boost::mutex> lock(cs);
164  return queue.size();
165  }
166 };
167 
169 {
173  {
174  }
175  std::string prefix;
178 };
179 
182 static struct event_base* eventBase = 0;
185 struct evhttp* eventHTTP = 0;
187 static std::vector<CSubNet> rpc_allow_subnets;
191 std::vector<HTTPPathHandler> pathHandlers;
193 std::vector<evhttp_bound_socket *> boundSockets;
194 
196 static bool ClientAllowed(const CNetAddr& netaddr)
197 {
198  if (!netaddr.IsValid())
199  return false;
200  BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
201  if (subnet.Match(netaddr))
202  return true;
203  return false;
204 }
205 
207 static bool InitHTTPAllowList()
208 {
209  rpc_allow_subnets.clear();
210  CNetAddr localv4;
211  CNetAddr localv6;
212  LookupHost("127.0.0.1", localv4, false);
213  LookupHost("::1", localv6, false);
214  rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
215  rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
216  if (mapMultiArgs.count("-rpcallowip")) {
217  const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
218  BOOST_FOREACH (std::string strAllow, vAllow) {
219  CSubNet subnet;
220  LookupSubNet(strAllow.c_str(), subnet);
221  if (!subnet.IsValid()) {
223  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),
225  return false;
226  }
227  rpc_allow_subnets.push_back(subnet);
228  }
229  }
230  std::string strAllowed;
231  BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
232  strAllowed += subnet.ToString() + " ";
233  LogPrint("http", "Allowing HTTP connections from: %s\n", strAllowed);
234  return true;
235 }
236 
239 {
240  switch (m) {
241  case HTTPRequest::GET:
242  return "GET";
243  break;
244  case HTTPRequest::POST:
245  return "POST";
246  break;
247  case HTTPRequest::HEAD:
248  return "HEAD";
249  break;
250  case HTTPRequest::PUT:
251  return "PUT";
252  break;
253  default:
254  return "unknown";
255  }
256 }
257 
259 static void http_request_cb(struct evhttp_request* req, void* arg)
260 {
261  std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
262 
263  LogPrint("http", "Received a %s request for %s from %s\n",
264  RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
265 
266  // Early address-based allow check
267  if (!ClientAllowed(hreq->GetPeer())) {
268  hreq->WriteReply(HTTP_FORBIDDEN);
269  return;
270  }
271 
272  // Early reject unknown HTTP methods
273  if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
274  hreq->WriteReply(HTTP_BADMETHOD);
275  return;
276  }
277 
278  // Find registered handler for prefix
279  std::string strURI = hreq->GetURI();
280  std::string path;
281  std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin();
282  std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end();
283  for (; i != iend; ++i) {
284  bool match = false;
285  if (i->exactMatch)
286  match = (strURI == i->prefix);
287  else
288  match = (strURI.substr(0, i->prefix.size()) == i->prefix);
289  if (match) {
290  path = strURI.substr(i->prefix.size());
291  break;
292  }
293  }
294 
295  // Dispatch to worker thread
296  if (i != iend) {
297  std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(hreq.release(), path, i->handler));
298  assert(workQueue);
299  if (workQueue->Enqueue(item.get()))
300  item.release(); /* if true, queue took ownership */
301  else
302  item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
303  } else {
304  hreq->WriteReply(HTTP_NOTFOUND);
305  }
306 }
307 
309 static void http_reject_request_cb(struct evhttp_request* req, void*)
310 {
311  LogPrint("http", "Rejecting request while shutting down\n");
312  evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL);
313 }
314 
316 static void ThreadHTTP(struct event_base* base, struct evhttp* http)
317 {
318  RenameThread("dash-http");
319  LogPrint("http", "Entering http event loop\n");
320  event_base_dispatch(base);
321  // Event loop will be interrupted by InterruptHTTPServer()
322  LogPrint("http", "Exited http event loop\n");
323 }
324 
326 static bool HTTPBindAddresses(struct evhttp* http)
327 {
328  int defaultPort = GetArg("-rpcport", BaseParams().RPCPort());
329  std::vector<std::pair<std::string, uint16_t> > endpoints;
330 
331  // Determine what addresses to bind to
332  if (!mapArgs.count("-rpcallowip")) { // Default to loopback if not allowing external IPs
333  endpoints.push_back(std::make_pair("::1", defaultPort));
334  endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
335  if (mapArgs.count("-rpcbind")) {
336  LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
337  }
338  } else if (mapArgs.count("-rpcbind")) { // Specific bind address
339  const std::vector<std::string>& vbind = mapMultiArgs["-rpcbind"];
340  for (std::vector<std::string>::const_iterator i = vbind.begin(); i != vbind.end(); ++i) {
341  int port = defaultPort;
342  std::string host;
343  SplitHostPort(*i, port, host);
344  endpoints.push_back(std::make_pair(host, port));
345  }
346  } else { // No specific bind address specified, bind to any
347  endpoints.push_back(std::make_pair("::", defaultPort));
348  endpoints.push_back(std::make_pair("0.0.0.0", defaultPort));
349  }
350 
351  // Bind addresses
352  for (std::vector<std::pair<std::string, uint16_t> >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) {
353  LogPrint("http", "Binding RPC on address %s port %i\n", i->first, i->second);
354  evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? NULL : i->first.c_str(), i->second);
355  if (bind_handle) {
356  boundSockets.push_back(bind_handle);
357  } else {
358  LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);
359  }
360  }
361  return !boundSockets.empty();
362 }
363 
366 {
367  RenameThread("dash-httpworker");
368  queue->Run();
369 }
370 
372 static void libevent_log_cb(int severity, const char *msg)
373 {
374 #ifndef EVENT_LOG_WARN
375 // EVENT_LOG_WARN was added in 2.0.19; but before then _EVENT_LOG_WARN existed.
376 # define EVENT_LOG_WARN _EVENT_LOG_WARN
377 #endif
378  if (severity >= EVENT_LOG_WARN) // Log warn messages and higher without debug category
379  LogPrintf("libevent: %s\n", msg);
380  else
381  LogPrint("libevent", "libevent: %s\n", msg);
382 }
383 
385 {
386  struct evhttp* http = 0;
387  struct event_base* base = 0;
388 
389  if (!InitHTTPAllowList())
390  return false;
391 
392  if (GetBoolArg("-rpcssl", false)) {
394  "SSL mode for RPC (-rpcssl) is no longer supported.",
396  return false;
397  }
398 
399  // Redirect libevent's logging to our own log
400  event_set_log_callback(&libevent_log_cb);
401 #if LIBEVENT_VERSION_NUMBER >= 0x02010100
402  // If -debug=libevent, set full libevent debugging.
403  // Otherwise, disable all libevent debugging.
404  if (LogAcceptCategory("libevent"))
405  event_enable_debug_logging(EVENT_DBG_ALL);
406  else
407  event_enable_debug_logging(EVENT_DBG_NONE);
408 #endif
409 #ifdef WIN32
410  evthread_use_windows_threads();
411 #else
412  evthread_use_pthreads();
413 #endif
414 
415  base = event_base_new(); // XXX RAII
416  if (!base) {
417  LogPrintf("Couldn't create an event_base: exiting\n");
418  return false;
419  }
420 
421  /* Create a new evhttp object to handle requests. */
422  http = evhttp_new(base); // XXX RAII
423  if (!http) {
424  LogPrintf("couldn't create evhttp. Exiting.\n");
425  event_base_free(base);
426  return false;
427  }
428 
429  evhttp_set_timeout(http, GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT));
430  evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE);
431  evhttp_set_max_body_size(http, MAX_SIZE);
432  evhttp_set_gencb(http, http_request_cb, NULL);
433 
434  if (!HTTPBindAddresses(http)) {
435  LogPrintf("Unable to bind any endpoint for RPC server\n");
436  evhttp_free(http);
437  event_base_free(base);
438  return false;
439  }
440 
441  LogPrint("http", "Initialized HTTP server\n");
442  int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
443  LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);
444 
445  workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
446  eventBase = base;
447  eventHTTP = http;
448  return true;
449 }
450 
451 boost::thread threadHTTP;
452 
454 {
455  LogPrint("http", "Starting HTTP server\n");
456  int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
457  LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
458  threadHTTP = boost::thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP));
459 
460  for (int i = 0; i < rpcThreads; i++)
461  boost::thread(boost::bind(&HTTPWorkQueueRun, workQueue));
462  return true;
463 }
464 
466 {
467  LogPrint("http", "Interrupting HTTP server\n");
468  if (eventHTTP) {
469  // Unlisten sockets
470  BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) {
471  evhttp_del_accept_socket(eventHTTP, socket);
472  }
473  // Reject requests on current connections
474  evhttp_set_gencb(eventHTTP, http_reject_request_cb, NULL);
475  }
476  if (workQueue)
477  workQueue->Interrupt();
478 }
479 
481 {
482  LogPrint("http", "Stopping HTTP server\n");
483  if (workQueue) {
484  LogPrint("http", "Waiting for HTTP worker threads to exit\n");
485 #ifndef WIN32
486  // ToDo: Disabling WaitExit() for Windows platforms is an ugly workaround for the wallet not
487  // closing during a repair-restart. It doesn't hurt, though, because threadHTTP.timed_join
488  // below takes care of this and sends a loopbreak.
489  workQueue->WaitExit();
490 #endif
491  delete workQueue;
492  }
493  if (eventBase) {
494  LogPrint("http", "Waiting for HTTP event thread to exit\n");
495  // Give event loop a few seconds to exit (to send back last RPC responses), then break it
496  // Before this was solved with event_base_loopexit, but that didn't work as expected in
497  // at least libevent 2.0.21 and always introduced a delay. In libevent
498  // master that appears to be solved, so in the future that solution
499  // could be used again (if desirable).
500  // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
501 #if BOOST_VERSION >= 105000
502  if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) {
503 #else
504  if (!threadHTTP.timed_join(boost::posix_time::milliseconds(2000))) {
505 #endif
506 
507  LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n");
508  event_base_loopbreak(eventBase);
509  threadHTTP.join();
510  }
511  }
512  if (eventHTTP) {
513  evhttp_free(eventHTTP);
514  eventHTTP = 0;
515  }
516  if (eventBase) {
517  event_base_free(eventBase);
518  eventBase = 0;
519  }
520  LogPrint("http", "Stopped HTTP server\n");
521 }
522 
523 struct event_base* EventBase()
524 {
525  return eventBase;
526 }
527 
528 static void httpevent_callback_fn(evutil_socket_t, short, void* data)
529 {
530  // Static handler: simply call inner handler
531  HTTPEvent *self = ((HTTPEvent*)data);
532  self->handler();
533  if (self->deleteWhenTriggered)
534  delete self;
535 }
536 
537 HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function<void(void)>& handler):
538  deleteWhenTriggered(deleteWhenTriggered), handler(handler)
539 {
540  ev = event_new(base, -1, 0, httpevent_callback_fn, this);
541  assert(ev);
542 }
544 {
545  event_free(ev);
546 }
547 void HTTPEvent::trigger(struct timeval* tv)
548 {
549  if (tv == NULL)
550  event_active(ev, 0, 0); // immediately trigger event in main thread
551  else
552  evtimer_add(ev, tv); // trigger after timeval passed
553 }
554 HTTPRequest::HTTPRequest(struct evhttp_request* req) : req(req),
555  replySent(false)
556 {
557 }
559 {
560  if (!replySent) {
561  // Keep track of whether reply was sent to avoid request leaks
562  LogPrintf("%s: Unhandled request\n", __func__);
563  WriteReply(HTTP_INTERNAL, "Unhandled request");
564  }
565  // evhttpd cleans up the request, as long as a reply was sent.
566 }
567 
568 std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
569 {
570  const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
571  assert(headers);
572  const char* val = evhttp_find_header(headers, hdr.c_str());
573  if (val)
574  return std::make_pair(true, val);
575  else
576  return std::make_pair(false, "");
577 }
578 
580 {
581  struct evbuffer* buf = evhttp_request_get_input_buffer(req);
582  if (!buf)
583  return "";
584  size_t size = evbuffer_get_length(buf);
591  const char* data = (const char*)evbuffer_pullup(buf, size);
592  if (!data) // returns NULL in case of empty buffer
593  return "";
594  std::string rv(data, size);
595  evbuffer_drain(buf, size);
596  return rv;
597 }
598 
599 void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value)
600 {
601  struct evkeyvalq* headers = evhttp_request_get_output_headers(req);
602  assert(headers);
603  evhttp_add_header(headers, hdr.c_str(), value.c_str());
604 }
605 
611 void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
612 {
613  assert(!replySent && req);
614  // Send event to main http thread to send reply message
615  struct evbuffer* evb = evhttp_request_get_output_buffer(req);
616  assert(evb);
617  evbuffer_add(evb, strReply.data(), strReply.size());
618  HTTPEvent* ev = new HTTPEvent(eventBase, true,
619  boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL));
620  ev->trigger(0);
621  replySent = true;
622  req = 0; // transferred back to main thread
623 }
624 
626 {
627  evhttp_connection* con = evhttp_request_get_connection(req);
628  CService peer;
629  if (con) {
630  // evhttp retains ownership over returned address string
631  const char* address = "";
632  uint16_t port = 0;
633  evhttp_connection_get_peer(con, (char**)&address, &port);
634  peer = LookupNumeric(address, port);
635  }
636  return peer;
637 }
638 
639 std::string HTTPRequest::GetURI()
640 {
641  return evhttp_request_get_uri(req);
642 }
643 
645 {
646  switch (evhttp_request_get_command(req)) {
647  case EVHTTP_REQ_GET:
648  return GET;
649  break;
650  case EVHTTP_REQ_POST:
651  return POST;
652  break;
653  case EVHTTP_REQ_HEAD:
654  return HEAD;
655  break;
656  case EVHTTP_REQ_PUT:
657  return PUT;
658  break;
659  default:
660  return UNKNOWN;
661  break;
662  }
663 }
664 
665 void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
666 {
667  LogPrint("http", "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
668  pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
669 }
670 
671 void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
672 {
673  std::vector<HTTPPathHandler>::iterator i = pathHandlers.begin();
674  std::vector<HTTPPathHandler>::iterator iend = pathHandlers.end();
675  for (; i != iend; ++i)
676  if (i->prefix == prefix && i->exactMatch == exactMatch)
677  break;
678  if (i != iend)
679  {
680  LogPrint("http", "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
681  pathHandlers.erase(i);
682  }
683 }
684 
std::deque< WorkItem * > queue
Definition: httpserver.cpp:75
bool(* handler)(HTTPRequest *req, const std::string &strReq)
Definition: rest.cpp:601
void Interrupt()
Definition: httpserver.cpp:145
boost::condition_variable CConditionVariable
Definition: sync.h:84
std::vector< evhttp_bound_socket * > boundSockets
Bound listening sockets.
Definition: httpserver.cpp:193
bool StartHTTPServer()
Definition: httpserver.cpp:453
void Run()
Definition: httpserver.cpp:126
static const int DEFAULT_HTTP_SERVER_TIMEOUT
Definition: httpserver.h:16
#define strprintf
Definition: tinyformat.h:1011
static const int DEFAULT_HTTP_WORKQUEUE
Definition: httpserver.h:15
ThreadCounter(WorkQueue &w)
Definition: httpserver.cpp:85
std::vector< HTTPPathHandler > pathHandlers
Handlers for (sub)paths.
Definition: httpserver.cpp:191
struct event_base * base
Definition: torcontrol.cpp:659
bool replySent
Definition: httpserver.h:59
HTTPPathHandler(std::string prefix, bool exactMatch, HTTPRequestHandler handler)
Definition: httpserver.cpp:171
std::string ToString() const
Definition: netaddress.cpp:660
CService LookupNumeric(const char *pszName, int portDefault)
Definition: netbase.cpp:228
HTTPEvent(struct event_base *base, bool deleteWhenTriggered, const boost::function< void(void)> &handler)
Definition: httpserver.cpp:537
const char * prefix
Definition: rest.cpp:600
bool running
Definition: httpserver.cpp:76
static void httpevent_callback_fn(evutil_socket_t, short, void *data)
Definition: httpserver.cpp:528
const CBaseChainParams & BaseParams()
bool IsValid() const
Definition: netaddress.cpp:186
std::string ReadBody()
Definition: httpserver.cpp:579
static std::vector< CSubNet > rpc_allow_subnets
List of subnets to allow RPC connections from.
Definition: httpserver.cpp:187
static void libevent_log_cb(int severity, const char *msg)
Definition: httpserver.cpp:372
std::string GetURI()
Definition: httpserver.cpp:639
void trigger(struct timeval *tv)
Definition: httpserver.cpp:547
static bool InitHTTPAllowList()
Definition: httpserver.cpp:207
void InterruptHTTPServer()
Definition: httpserver.cpp:465
void RenameThread(const char *name)
Definition: util.cpp:873
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Definition: ui_interface.h:77
static bool HTTPBindAddresses(struct evhttp *http)
Definition: httpserver.cpp:326
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Definition: httpserver.cpp:665
#define L(x0, x1, x2, x3, x4, x5, x6, x7)
Definition: jh.c:501
static std::string RequestMethodString(HTTPRequest::RequestMethod m)
Definition: httpserver.cpp:238
int numThreads
Definition: httpserver.cpp:78
static void http_reject_request_cb(struct evhttp_request *req, void *)
Definition: httpserver.cpp:309
bool InitHTTPServer()
Definition: httpserver.cpp:384
size_t maxDepth
Definition: httpserver.cpp:77
bool GetBoolArg(const std::string &strArg, bool fDefault)
Definition: util.cpp:455
#define LogPrintf(...)
Definition: util.h:98
HTTPRequestHandler handler
Definition: httpserver.cpp:177
void StopHTTPServer()
Definition: httpserver.cpp:480
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
CWaitableCriticalSection cs
Definition: httpserver.cpp:72
void WriteReply(int nStatus, const std::string &strReply="")
Definition: httpserver.cpp:611
void operator()()
Definition: httpserver.cpp:52
CClientUIInterface uiInterface
Definition: init.cpp:130
std::string prefix
Definition: httpserver.cpp:175
size_t Depth()
Definition: httpserver.cpp:161
struct event * ev
Definition: httpserver.h:146
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Definition: httpserver.cpp:671
boost::function< void(void)> handler
Definition: httpserver.h:144
HTTPRequestHandler func
Definition: httpserver.cpp:61
boost::thread threadHTTP
Definition: httpserver.cpp:451
struct event_base * EventBase()
Definition: httpserver.cpp:523
std::pair< bool, std::string > GetHeader(const std::string &hdr)
Definition: httpserver.cpp:568
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:640
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Definition: netbase.cpp:61
static bool ClientAllowed(const CNetAddr &netaddr)
Definition: httpserver.cpp:196
HTTPWorkItem(HTTPRequest *req, const std::string &path, const HTTPRequestHandler &func)
Definition: httpserver.cpp:48
HTTPRequest(struct evhttp_request *req)
Definition: httpserver.cpp:554
bool IsValid() const
Definition: netaddress.cpp:698
static WorkQueue< HTTPClosure > * workQueue
Work queue for handling longer requests off the event loop thread.
Definition: httpserver.cpp:189
void WaitExit()
Definition: httpserver.cpp:152
CService GetPeer()
Definition: httpserver.cpp:625
#define EVENT_LOG_WARN
static const unsigned int MAX_SIZE
Definition: serialize.h:26
RequestMethod GetRequestMethod()
Definition: httpserver.cpp:644
static void HTTPWorkQueueRun(WorkQueue< HTTPClosure > *queue)
Definition: httpserver.cpp:365
bool LogAcceptCategory(const char *category)
Definition: util.cpp:247
struct evhttp_request * req
Definition: httpserver.h:58
static int count
Definition: tests.c:41
static const size_t MAX_HEADERS_SIZE
Definition: httpserver.cpp:42
static void http_request_cb(struct evhttp_request *req, void *arg)
Definition: httpserver.cpp:259
void WriteHeader(const std::string &hdr, const std::string &value)
Definition: httpserver.cpp:599
CConditionVariable cond
Definition: httpserver.cpp:73
boost::scoped_ptr< HTTPRequest > req
Definition: httpserver.cpp:57
WorkQueue(size_t maxDepth)
Definition: httpserver.cpp:99
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Definition: util.cpp:441
std::string path
Definition: httpserver.cpp:60
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:177
int port
Definition: zmq_sub.py:8
boost::function< void(HTTPRequest *req, const std::string &)> HTTPRequestHandler
Definition: httpserver.h:38
map< string, vector< string > > mapMultiArgs
Definition: util.cpp:123
bool Match(const CNetAddr &addr) const
Definition: netaddress.cpp:634
struct evhttp * eventHTTP
HTTP server.
Definition: httpserver.cpp:185
bool Enqueue(WorkItem *item)
Definition: httpserver.cpp:115
static const int DEFAULT_HTTP_THREADS
Definition: httpserver.h:14
static void ThreadHTTP(struct event_base *base, struct evhttp *http)
Definition: httpserver.cpp:316
map< string, string > mapArgs
Definition: util.cpp:122
static struct event_base * eventBase
libevent event loop
Definition: httpserver.cpp:183