Changeset View
Changeset View
Standalone View
Standalone View
src/httpserver.cpp
Show All 14 Lines | |||||
#include "util.h" | #include "util.h" | ||||
#include "utilstrencodings.h" | #include "utilstrencodings.h" | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <event2/buffer.h> | #include <event2/buffer.h> | ||||
#include <event2/bufferevent.h> | |||||
#include <event2/event.h> | #include <event2/event.h> | ||||
#include <event2/http.h> | #include <event2/http.h> | ||||
#include <event2/keyvalq_struct.h> | #include <event2/keyvalq_struct.h> | ||||
#include <event2/thread.h> | #include <event2/thread.h> | ||||
#include <event2/util.h> | #include <event2/util.h> | ||||
#ifdef EVENT__HAVE_NETINET_IN_H | #ifdef EVENT__HAVE_NETINET_IN_H | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | switch (m) { | ||||
return "unknown"; | return "unknown"; | ||||
} | } | ||||
} | } | ||||
/** HTTP request callback */ | /** HTTP request callback */ | ||||
static void http_request_cb(struct evhttp_request *req, void *arg) { | static void http_request_cb(struct evhttp_request *req, void *arg) { | ||||
Config &config = *reinterpret_cast<Config *>(arg); | Config &config = *reinterpret_cast<Config *>(arg); | ||||
// Disable reading to work around a libevent bug, fixed in 2.2.0. | |||||
if (event_get_version_number() >= 0x02010600 && | |||||
event_get_version_number() < 0x02020001) { | |||||
evhttp_connection *conn = evhttp_request_get_connection(req); | |||||
if (conn) { | |||||
bufferevent *bev = evhttp_connection_get_bufferevent(conn); | |||||
if (bev) { | |||||
bufferevent_disable(bev, EV_READ); | |||||
} | |||||
} | |||||
} | |||||
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req)); | std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req)); | ||||
LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n", | LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n", | ||||
RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), | RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), | ||||
hreq->GetPeer().ToString()); | hreq->GetPeer().ToString()); | ||||
// Early address-based allow check | // Early address-based allow check | ||||
if (!ClientAllowed(hreq->GetPeer())) { | if (!ClientAllowed(hreq->GetPeer())) { | ||||
▲ Show 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | |||||
* done from worker threads. | * done from worker threads. | ||||
*/ | */ | ||||
void HTTPRequest::WriteReply(int nStatus, const std::string &strReply) { | void HTTPRequest::WriteReply(int nStatus, const std::string &strReply) { | ||||
assert(!replySent && req); | assert(!replySent && req); | ||||
// Send event to main http thread to send reply message | // Send event to main http thread to send reply message | ||||
struct evbuffer *evb = evhttp_request_get_output_buffer(req); | struct evbuffer *evb = evhttp_request_get_output_buffer(req); | ||||
assert(evb); | assert(evb); | ||||
evbuffer_add(evb, strReply.data(), strReply.size()); | evbuffer_add(evb, strReply.data(), strReply.size()); | ||||
HTTPEvent *ev = new HTTPEvent(eventBase, true, | auto req_copy = req; | ||||
std::bind(evhttp_send_reply, req, nStatus, | HTTPEvent *ev = new HTTPEvent(eventBase, true, [req_copy, nStatus] { | ||||
(const char *)nullptr, | evhttp_send_reply(req_copy, nStatus, nullptr, nullptr); | ||||
(struct evbuffer *)nullptr)); | // Re-enable reading from the socket. This is the second part of the | ||||
// libevent workaround above. | |||||
if (event_get_version_number() >= 0x02010600 && | |||||
event_get_version_number() < 0x02020001) { | |||||
evhttp_connection *conn = evhttp_request_get_connection(req_copy); | |||||
if (conn) { | |||||
bufferevent *bev = evhttp_connection_get_bufferevent(conn); | |||||
if (bev) { | |||||
bufferevent_enable(bev, EV_READ | EV_WRITE); | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
ev->trigger(nullptr); | ev->trigger(nullptr); | ||||
replySent = true; | replySent = true; | ||||
// transferred back to main thread. | // transferred back to main thread. | ||||
req = nullptr; | req = nullptr; | ||||
} | } | ||||
CService HTTPRequest::GetPeer() { | CService HTTPRequest::GetPeer() { | ||||
evhttp_connection *con = evhttp_request_get_connection(req); | evhttp_connection *con = evhttp_request_get_connection(req); | ||||
▲ Show 20 Lines • Show All 51 Lines • Show Last 20 Lines |