You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

httpserver.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. // Copyright (c) 2015-2016 The Starwels developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "httpserver.h"
  5. #include "chainparamsbase.h"
  6. #include "compat.h"
  7. #include "util.h"
  8. #include "utilstrencodings.h"
  9. #include "netbase.h"
  10. #include "rpc/protocol.h" // For HTTP status codes
  11. #include "sync.h"
  12. #include "ui_interface.h"
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <signal.h>
  19. #include <future>
  20. #include <event2/thread.h>
  21. #include <event2/buffer.h>
  22. #include <event2/bufferevent.h>
  23. #include <event2/util.h>
  24. #include <event2/keyvalq_struct.h>
  25. #include "support/events.h"
  26. #ifdef EVENT__HAVE_NETINET_IN_H
  27. #include <netinet/in.h>
  28. #ifdef _XOPEN_SOURCE_EXTENDED
  29. #include <arpa/inet.h>
  30. #endif
  31. #endif
  32. /** Maximum size of http request (request line + headers) */
  33. static const size_t MAX_HEADERS_SIZE = 8192;
  34. /** HTTP request work item */
  35. class HTTPWorkItem : public HTTPClosure
  36. {
  37. public:
  38. HTTPWorkItem(std::unique_ptr<HTTPRequest> _req, const std::string &_path, const HTTPRequestHandler& _func):
  39. req(std::move(_req)), path(_path), func(_func)
  40. {
  41. }
  42. void operator()() override
  43. {
  44. func(req.get(), path);
  45. }
  46. std::unique_ptr<HTTPRequest> req;
  47. private:
  48. std::string path;
  49. HTTPRequestHandler func;
  50. };
  51. /** Simple work queue for distributing work over multiple threads.
  52. * Work items are simply callable objects.
  53. */
  54. template <typename WorkItem>
  55. class WorkQueue
  56. {
  57. private:
  58. /** Mutex protects entire object */
  59. std::mutex cs;
  60. std::condition_variable cond;
  61. std::deque<std::unique_ptr<WorkItem>> queue;
  62. bool running;
  63. size_t maxDepth;
  64. int numThreads;
  65. /** RAII object to keep track of number of running worker threads */
  66. class ThreadCounter
  67. {
  68. public:
  69. WorkQueue &wq;
  70. ThreadCounter(WorkQueue &w): wq(w)
  71. {
  72. std::lock_guard<std::mutex> lock(wq.cs);
  73. wq.numThreads += 1;
  74. }
  75. ~ThreadCounter()
  76. {
  77. std::lock_guard<std::mutex> lock(wq.cs);
  78. wq.numThreads -= 1;
  79. wq.cond.notify_all();
  80. }
  81. };
  82. public:
  83. WorkQueue(size_t _maxDepth) : running(true),
  84. maxDepth(_maxDepth),
  85. numThreads(0)
  86. {
  87. }
  88. /** Precondition: worker threads have all stopped
  89. * (call WaitExit)
  90. */
  91. ~WorkQueue()
  92. {
  93. }
  94. /** Enqueue a work item */
  95. bool Enqueue(WorkItem* item)
  96. {
  97. std::unique_lock<std::mutex> lock(cs);
  98. if (queue.size() >= maxDepth) {
  99. return false;
  100. }
  101. queue.emplace_back(std::unique_ptr<WorkItem>(item));
  102. cond.notify_one();
  103. return true;
  104. }
  105. /** Thread function */
  106. void Run()
  107. {
  108. ThreadCounter count(*this);
  109. while (true) {
  110. std::unique_ptr<WorkItem> i;
  111. {
  112. std::unique_lock<std::mutex> lock(cs);
  113. while (running && queue.empty())
  114. cond.wait(lock);
  115. if (!running)
  116. break;
  117. i = std::move(queue.front());
  118. queue.pop_front();
  119. }
  120. (*i)();
  121. }
  122. }
  123. /** Interrupt and exit loops */
  124. void Interrupt()
  125. {
  126. std::unique_lock<std::mutex> lock(cs);
  127. running = false;
  128. cond.notify_all();
  129. }
  130. /** Wait for worker threads to exit */
  131. void WaitExit()
  132. {
  133. std::unique_lock<std::mutex> lock(cs);
  134. while (numThreads > 0)
  135. cond.wait(lock);
  136. }
  137. };
  138. struct HTTPPathHandler
  139. {
  140. HTTPPathHandler() {}
  141. HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler):
  142. prefix(_prefix), exactMatch(_exactMatch), handler(_handler)
  143. {
  144. }
  145. std::string prefix;
  146. bool exactMatch;
  147. HTTPRequestHandler handler;
  148. };
  149. /** HTTP module state */
  150. //! libevent event loop
  151. static struct event_base* eventBase = 0;
  152. //! HTTP server
  153. struct evhttp* eventHTTP = 0;
  154. //! List of subnets to allow RPC connections from
  155. static std::vector<CSubNet> rpc_allow_subnets;
  156. //! Work queue for handling longer requests off the event loop thread
  157. static WorkQueue<HTTPClosure>* workQueue = 0;
  158. //! Handlers for (sub)paths
  159. std::vector<HTTPPathHandler> pathHandlers;
  160. //! Bound listening sockets
  161. std::vector<evhttp_bound_socket *> boundSockets;
  162. /** Check if a network address is allowed to access the HTTP server */
  163. static bool ClientAllowed(const CNetAddr& netaddr)
  164. {
  165. if (!netaddr.IsValid())
  166. return false;
  167. for(const CSubNet& subnet : rpc_allow_subnets)
  168. if (subnet.Match(netaddr))
  169. return true;
  170. return false;
  171. }
  172. /** Initialize ACL list for HTTP server */
  173. static bool InitHTTPAllowList()
  174. {
  175. rpc_allow_subnets.clear();
  176. CNetAddr localv4;
  177. CNetAddr localv6;
  178. LookupHost("127.0.0.1", localv4, false);
  179. LookupHost("::1", localv6, false);
  180. rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
  181. rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
  182. for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) {
  183. CSubNet subnet;
  184. LookupSubNet(strAllow.c_str(), subnet);
  185. if (!subnet.IsValid()) {
  186. uiInterface.ThreadSafeMessageBox(
  187. 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),
  188. "", CClientUIInterface::MSG_ERROR);
  189. return false;
  190. }
  191. rpc_allow_subnets.push_back(subnet);
  192. }
  193. std::string strAllowed;
  194. for (const CSubNet& subnet : rpc_allow_subnets)
  195. strAllowed += subnet.ToString() + " ";
  196. LogPrint(BCLog::HTTP, "Allowing HTTP connections from: %s\n", strAllowed);
  197. return true;
  198. }
  199. /** HTTP request method as string - use for logging only */
  200. static std::string RequestMethodString(HTTPRequest::RequestMethod m)
  201. {
  202. switch (m) {
  203. case HTTPRequest::GET:
  204. return "GET";
  205. break;
  206. case HTTPRequest::POST:
  207. return "POST";
  208. break;
  209. case HTTPRequest::HEAD:
  210. return "HEAD";
  211. break;
  212. case HTTPRequest::PUT:
  213. return "PUT";
  214. break;
  215. default:
  216. return "unknown";
  217. }
  218. }
  219. /** HTTP request callback */
  220. static void http_request_cb(struct evhttp_request* req, void* arg)
  221. {
  222. // Disable reading to work around a libevent bug, fixed in 2.2.0.
  223. if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
  224. evhttp_connection* conn = evhttp_request_get_connection(req);
  225. if (conn) {
  226. bufferevent* bev = evhttp_connection_get_bufferevent(conn);
  227. if (bev) {
  228. bufferevent_disable(bev, EV_READ);
  229. }
  230. }
  231. }
  232. std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
  233. LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
  234. RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
  235. // Early address-based allow check
  236. if (!ClientAllowed(hreq->GetPeer())) {
  237. hreq->WriteReply(HTTP_FORBIDDEN);
  238. return;
  239. }
  240. // Early reject unknown HTTP methods
  241. if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
  242. hreq->WriteReply(HTTP_BADMETHOD);
  243. return;
  244. }
  245. // Find registered handler for prefix
  246. std::string strURI = hreq->GetURI();
  247. std::string path;
  248. std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin();
  249. std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end();
  250. for (; i != iend; ++i) {
  251. bool match = false;
  252. if (i->exactMatch)
  253. match = (strURI == i->prefix);
  254. else
  255. match = (strURI.substr(0, i->prefix.size()) == i->prefix);
  256. if (match) {
  257. path = strURI.substr(i->prefix.size());
  258. break;
  259. }
  260. }
  261. // Dispatch to worker thread
  262. if (i != iend) {
  263. std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(std::move(hreq), path, i->handler));
  264. assert(workQueue);
  265. if (workQueue->Enqueue(item.get()))
  266. item.release(); /* if true, queue took ownership */
  267. else {
  268. LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n");
  269. item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
  270. }
  271. } else {
  272. hreq->WriteReply(HTTP_NOTFOUND);
  273. }
  274. }
  275. /** Callback to reject HTTP requests after shutdown. */
  276. static void http_reject_request_cb(struct evhttp_request* req, void*)
  277. {
  278. LogPrint(BCLog::HTTP, "Rejecting request while shutting down\n");
  279. evhttp_send_error(req, HTTP_SERVUNAVAIL, nullptr);
  280. }
  281. /** Event dispatcher thread */
  282. static bool ThreadHTTP(struct event_base* base, struct evhttp* http)
  283. {
  284. RenameThread("starwels-http");
  285. LogPrint(BCLog::HTTP, "Entering http event loop\n");
  286. event_base_dispatch(base);
  287. // Event loop will be interrupted by InterruptHTTPServer()
  288. LogPrint(BCLog::HTTP, "Exited http event loop\n");
  289. return event_base_got_break(base) == 0;
  290. }
  291. /** Bind HTTP server to specified addresses */
  292. static bool HTTPBindAddresses(struct evhttp* http)
  293. {
  294. int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
  295. std::vector<std::pair<std::string, uint16_t> > endpoints;
  296. // Determine what addresses to bind to
  297. if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs
  298. endpoints.push_back(std::make_pair("::1", defaultPort));
  299. endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
  300. if (gArgs.IsArgSet("-rpcbind")) {
  301. LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
  302. }
  303. } else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
  304. for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
  305. int port = defaultPort;
  306. std::string host;
  307. SplitHostPort(strRPCBind, port, host);
  308. endpoints.push_back(std::make_pair(host, port));
  309. }
  310. } else { // No specific bind address specified, bind to any
  311. endpoints.push_back(std::make_pair("::", defaultPort));
  312. endpoints.push_back(std::make_pair("0.0.0.0", defaultPort));
  313. }
  314. // Bind addresses
  315. for (std::vector<std::pair<std::string, uint16_t> >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) {
  316. LogPrint(BCLog::HTTP, "Binding RPC on address %s port %i\n", i->first, i->second);
  317. evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second);
  318. if (bind_handle) {
  319. boundSockets.push_back(bind_handle);
  320. } else {
  321. LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);
  322. }
  323. }
  324. return !boundSockets.empty();
  325. }
  326. /** Simple wrapper to set thread name and run work queue */
  327. static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue)
  328. {
  329. RenameThread("starwels-httpworker");
  330. queue->Run();
  331. }
  332. /** libevent event log callback */
  333. static void libevent_log_cb(int severity, const char *msg)
  334. {
  335. #ifndef EVENT_LOG_WARN
  336. // EVENT_LOG_WARN was added in 2.0.19; but before then _EVENT_LOG_WARN existed.
  337. # define EVENT_LOG_WARN _EVENT_LOG_WARN
  338. #endif
  339. if (severity >= EVENT_LOG_WARN) // Log warn messages and higher without debug category
  340. LogPrintf("libevent: %s\n", msg);
  341. else
  342. LogPrint(BCLog::LIBEVENT, "libevent: %s\n", msg);
  343. }
  344. bool InitHTTPServer()
  345. {
  346. if (!InitHTTPAllowList())
  347. return false;
  348. if (gArgs.GetBoolArg("-rpcssl", false)) {
  349. uiInterface.ThreadSafeMessageBox(
  350. "SSL mode for RPC (-rpcssl) is no longer supported.",
  351. "", CClientUIInterface::MSG_ERROR);
  352. return false;
  353. }
  354. // Redirect libevent's logging to our own log
  355. event_set_log_callback(&libevent_log_cb);
  356. // Update libevent's log handling. Returns false if our version of
  357. // libevent doesn't support debug logging, in which case we should
  358. // clear the BCLog::LIBEVENT flag.
  359. if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
  360. logCategories &= ~BCLog::LIBEVENT;
  361. }
  362. #ifdef WIN32
  363. evthread_use_windows_threads();
  364. #else
  365. evthread_use_pthreads();
  366. #endif
  367. raii_event_base base_ctr = obtain_event_base();
  368. /* Create a new evhttp object to handle requests. */
  369. raii_evhttp http_ctr = obtain_evhttp(base_ctr.get());
  370. struct evhttp* http = http_ctr.get();
  371. if (!http) {
  372. LogPrintf("couldn't create evhttp. Exiting.\n");
  373. return false;
  374. }
  375. evhttp_set_timeout(http, gArgs.GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT));
  376. evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE);
  377. evhttp_set_max_body_size(http, MAX_SIZE);
  378. evhttp_set_gencb(http, http_request_cb, nullptr);
  379. if (!HTTPBindAddresses(http)) {
  380. LogPrintf("Unable to bind any endpoint for RPC server\n");
  381. return false;
  382. }
  383. LogPrint(BCLog::HTTP, "Initialized HTTP server\n");
  384. int workQueueDepth = std::max((long)gArgs.GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
  385. LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);
  386. workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
  387. // tranfer ownership to eventBase/HTTP via .release()
  388. eventBase = base_ctr.release();
  389. eventHTTP = http_ctr.release();
  390. return true;
  391. }
  392. bool UpdateHTTPServerLogging(bool enable) {
  393. #if LIBEVENT_VERSION_NUMBER >= 0x02010100
  394. if (enable) {
  395. event_enable_debug_logging(EVENT_DBG_ALL);
  396. } else {
  397. event_enable_debug_logging(EVENT_DBG_NONE);
  398. }
  399. return true;
  400. #else
  401. // Can't update libevent logging if version < 02010100
  402. return false;
  403. #endif
  404. }
  405. std::thread threadHTTP;
  406. std::future<bool> threadResult;
  407. bool StartHTTPServer()
  408. {
  409. LogPrint(BCLog::HTTP, "Starting HTTP server\n");
  410. int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
  411. LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
  412. std::packaged_task<bool(event_base*, evhttp*)> task(ThreadHTTP);
  413. threadResult = task.get_future();
  414. threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
  415. for (int i = 0; i < rpcThreads; i++) {
  416. std::thread rpc_worker(HTTPWorkQueueRun, workQueue);
  417. rpc_worker.detach();
  418. }
  419. return true;
  420. }
  421. void InterruptHTTPServer()
  422. {
  423. LogPrint(BCLog::HTTP, "Interrupting HTTP server\n");
  424. if (eventHTTP) {
  425. // Unlisten sockets
  426. for (evhttp_bound_socket *socket : boundSockets) {
  427. evhttp_del_accept_socket(eventHTTP, socket);
  428. }
  429. // Reject requests on current connections
  430. evhttp_set_gencb(eventHTTP, http_reject_request_cb, nullptr);
  431. }
  432. if (workQueue)
  433. workQueue->Interrupt();
  434. }
  435. void StopHTTPServer()
  436. {
  437. LogPrint(BCLog::HTTP, "Stopping HTTP server\n");
  438. if (workQueue) {
  439. LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
  440. workQueue->WaitExit();
  441. delete workQueue;
  442. workQueue = nullptr;
  443. }
  444. if (eventBase) {
  445. LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n");
  446. // Give event loop a few seconds to exit (to send back last RPC responses), then break it
  447. // Before this was solved with event_base_loopexit, but that didn't work as expected in
  448. // at least libevent 2.0.21 and always introduced a delay. In libevent
  449. // master that appears to be solved, so in the future that solution
  450. // could be used again (if desirable).
  451. // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
  452. if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) {
  453. LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n");
  454. event_base_loopbreak(eventBase);
  455. }
  456. threadHTTP.join();
  457. }
  458. if (eventHTTP) {
  459. evhttp_free(eventHTTP);
  460. eventHTTP = 0;
  461. }
  462. if (eventBase) {
  463. event_base_free(eventBase);
  464. eventBase = 0;
  465. }
  466. LogPrint(BCLog::HTTP, "Stopped HTTP server\n");
  467. }
  468. struct event_base* EventBase()
  469. {
  470. return eventBase;
  471. }
  472. static void httpevent_callback_fn(evutil_socket_t, short, void* data)
  473. {
  474. // Static handler: simply call inner handler
  475. HTTPEvent *self = ((HTTPEvent*)data);
  476. self->handler();
  477. if (self->deleteWhenTriggered)
  478. delete self;
  479. }
  480. HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function<void(void)>& _handler):
  481. deleteWhenTriggered(_deleteWhenTriggered), handler(_handler)
  482. {
  483. ev = event_new(base, -1, 0, httpevent_callback_fn, this);
  484. assert(ev);
  485. }
  486. HTTPEvent::~HTTPEvent()
  487. {
  488. event_free(ev);
  489. }
  490. void HTTPEvent::trigger(struct timeval* tv)
  491. {
  492. if (tv == nullptr)
  493. event_active(ev, 0, 0); // immediately trigger event in main thread
  494. else
  495. evtimer_add(ev, tv); // trigger after timeval passed
  496. }
  497. HTTPRequest::HTTPRequest(struct evhttp_request* _req) : req(_req),
  498. replySent(false)
  499. {
  500. }
  501. HTTPRequest::~HTTPRequest()
  502. {
  503. if (!replySent) {
  504. // Keep track of whether reply was sent to avoid request leaks
  505. LogPrintf("%s: Unhandled request\n", __func__);
  506. WriteReply(HTTP_INTERNAL, "Unhandled request");
  507. }
  508. // evhttpd cleans up the request, as long as a reply was sent.
  509. }
  510. std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
  511. {
  512. const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
  513. assert(headers);
  514. const char* val = evhttp_find_header(headers, hdr.c_str());
  515. if (val)
  516. return std::make_pair(true, val);
  517. else
  518. return std::make_pair(false, "");
  519. }
  520. std::string HTTPRequest::ReadBody()
  521. {
  522. struct evbuffer* buf = evhttp_request_get_input_buffer(req);
  523. if (!buf)
  524. return "";
  525. size_t size = evbuffer_get_length(buf);
  526. /** Trivial implementation: if this is ever a performance bottleneck,
  527. * internal copying can be avoided in multi-segment buffers by using
  528. * evbuffer_peek and an awkward loop. Though in that case, it'd be even
  529. * better to not copy into an intermediate string but use a stream
  530. * abstraction to consume the evbuffer on the fly in the parsing algorithm.
  531. */
  532. const char* data = (const char*)evbuffer_pullup(buf, size);
  533. if (!data) // returns nullptr in case of empty buffer
  534. return "";
  535. std::string rv(data, size);
  536. evbuffer_drain(buf, size);
  537. return rv;
  538. }
  539. void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value)
  540. {
  541. struct evkeyvalq* headers = evhttp_request_get_output_headers(req);
  542. assert(headers);
  543. evhttp_add_header(headers, hdr.c_str(), value.c_str());
  544. }
  545. /** Closure sent to main thread to request a reply to be sent to
  546. * a HTTP request.
  547. * Replies must be sent in the main loop in the main http thread,
  548. * this cannot be done from worker threads.
  549. */
  550. void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
  551. {
  552. assert(!replySent && req);
  553. // Send event to main http thread to send reply message
  554. struct evbuffer* evb = evhttp_request_get_output_buffer(req);
  555. assert(evb);
  556. evbuffer_add(evb, strReply.data(), strReply.size());
  557. auto req_copy = req;
  558. HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{
  559. evhttp_send_reply(req_copy, nStatus, nullptr, nullptr);
  560. // Re-enable reading from the socket. This is the second part of the libevent
  561. // workaround above.
  562. if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
  563. evhttp_connection* conn = evhttp_request_get_connection(req_copy);
  564. if (conn) {
  565. bufferevent* bev = evhttp_connection_get_bufferevent(conn);
  566. if (bev) {
  567. bufferevent_enable(bev, EV_READ | EV_WRITE);
  568. }
  569. }
  570. }
  571. });
  572. ev->trigger(nullptr);
  573. replySent = true;
  574. req = nullptr; // transferred back to main thread
  575. }
  576. CService HTTPRequest::GetPeer()
  577. {
  578. evhttp_connection* con = evhttp_request_get_connection(req);
  579. CService peer;
  580. if (con) {
  581. // evhttp retains ownership over returned address string
  582. const char* address = "";
  583. uint16_t port = 0;
  584. evhttp_connection_get_peer(con, (char**)&address, &port);
  585. peer = LookupNumeric(address, port);
  586. }
  587. return peer;
  588. }
  589. std::string HTTPRequest::GetURI()
  590. {
  591. return evhttp_request_get_uri(req);
  592. }
  593. HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod()
  594. {
  595. switch (evhttp_request_get_command(req)) {
  596. case EVHTTP_REQ_GET:
  597. return GET;
  598. break;
  599. case EVHTTP_REQ_POST:
  600. return POST;
  601. break;
  602. case EVHTTP_REQ_HEAD:
  603. return HEAD;
  604. break;
  605. case EVHTTP_REQ_PUT:
  606. return PUT;
  607. break;
  608. default:
  609. return UNKNOWN;
  610. break;
  611. }
  612. }
  613. void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
  614. {
  615. LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
  616. pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
  617. }
  618. void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
  619. {
  620. std::vector<HTTPPathHandler>::iterator i = pathHandlers.begin();
  621. std::vector<HTTPPathHandler>::iterator iend = pathHandlers.end();
  622. for (; i != iend; ++i)
  623. if (i->prefix == prefix && i->exactMatch == exactMatch)
  624. break;
  625. if (i != iend)
  626. {
  627. LogPrint(BCLog::HTTP, "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
  628. pathHandlers.erase(i);
  629. }
  630. }
  631. std::string urlDecode(const std::string &urlEncoded) {
  632. std::string res;
  633. if (!urlEncoded.empty()) {
  634. char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
  635. if (decoded) {
  636. res = std::string(decoded);
  637. free(decoded);
  638. }
  639. }
  640. return res;
  641. }