1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
#include "server/handler_v2.h"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <algorithm>
#include <string>
#include <vector>
#include "log/cert.h"
#include "log/cert_checker.h"
#include "log/cluster_state_controller.h"
#include "log/log_lookup.h"
#include "log/logged_entry.h"
#include "monitoring/latency.h"
#include "monitoring/monitoring.h"
#include "server/json_output.h"
#include "server/proxy.h"
#include "util/json_wrapper.h"
#include "util/thread_pool.h"
namespace libevent = cert_trans::libevent;
using cert_trans::Counter;
using cert_trans::HttpHandlerV2;
using cert_trans::Latency;
using cert_trans::LoggedEntry;
using cert_trans::Proxy;
using cert_trans::ScopedLatency;
using ct::ShortMerkleAuditProof;
using ct::SignedCertificateTimestamp;
using ct::SignedTreeHead;
using std::bind;
using std::chrono::milliseconds;
using std::chrono::seconds;
using std::lock_guard;
using std::make_shared;
using std::multimap;
using std::min;
using std::mutex;
using std::placeholders::_1;
using std::string;
using std::unique_ptr;
using std::vector;
DEFINE_int32(max_leaf_entries_per_response, 1000,
"maximum number of entries to put in the response of a "
"get-entries request");
namespace {
static Latency<milliseconds, string> http_server_request_latency_ms(
"total_http_server_request_latency_ms", "path",
"Total request latency in ms broken down by path");
} // namespace
HttpHandlerV2::HttpHandlerV2(LogLookup* log_lookup, const ReadOnlyDatabase* db,
const ClusterStateController* controller,
ThreadPool* pool, libevent::Base* event_base,
StalenessTracker* staleness_tracker)
: log_lookup_(CHECK_NOTNULL(log_lookup)),
db_(CHECK_NOTNULL(db)),
controller_(CHECK_NOTNULL(controller)),
proxy_(nullptr),
pool_(CHECK_NOTNULL(pool)),
event_base_(CHECK_NOTNULL(event_base)),
staleness_tracker_(CHECK_NOTNULL(staleness_tracker)) {
}
HttpHandlerV2::~HttpHandlerV2() {
}
void StatsHandlerInterceptor(const string& path,
const libevent::HttpServer::HandlerCallback& cb,
evhttp_request* req) {
ScopedLatency total_http_server_request_latency(
http_server_request_latency_ms.GetScopedLatency(path));
cb(req);
}
void HttpHandlerV2::AddEntryReply(
evhttp_request* req, const util::Status& add_status,
const SignedCertificateTimestamp& sct) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
void HttpHandlerV2::ProxyInterceptor(
const libevent::HttpServer::HandlerCallback& local_handler,
evhttp_request* request) {
VLOG(2) << "Running proxy interceptor...";
// TODO(alcutter): We can be a bit smarter about when to proxy off
// the request - being stale wrt to the current serving STH doesn't
// automatically mean we're unable to answer this request.
if (staleness_tracker_->IsNodeStale()) {
// Can't do this on the libevent thread since it can block on the lock in
// ClusterStatusController::GetFreshNodes().
pool_->Add(bind(&Proxy::ProxyRequest, proxy_, request));
} else {
local_handler(request);
}
}
void HttpHandlerV2::AddProxyWrappedHandler(
libevent::HttpServer* server, const string& path,
const libevent::HttpServer::HandlerCallback& local_handler) {
const libevent::HttpServer::HandlerCallback stats_handler(
bind(&StatsHandlerInterceptor, path, local_handler, _1));
CHECK(server->AddHandler(path, bind(&HttpHandlerV2::ProxyInterceptor, this,
stats_handler, _1)));
}
void HttpHandlerV2::Add(libevent::HttpServer* server) {
CHECK_NOTNULL(server);
// TODO(pphaneuf): An optional prefix might be nice?
// TODO(pphaneuf): Find out which methods are CPU intensive enough
// that they should be spun off to the thread pool.
AddProxyWrappedHandler(server, "/ct/v2/get-entries",
bind(&HttpHandlerV2::GetEntries, this, _1));
AddProxyWrappedHandler(server, "/ct/v2/get-proof-by-hash",
bind(&HttpHandlerV2::GetProof, this, _1));
AddProxyWrappedHandler(server, "/ct/v2/get-sth",
bind(&HttpHandlerV2::GetSTH, this, _1));
AddProxyWrappedHandler(server, "/ct/v2/get-sth-consistency",
bind(&HttpHandlerV2::GetConsistency, this, _1));
// Now add any sub-class handlers.
AddHandlers(server);
}
void HttpHandlerV2::SetProxy(Proxy* proxy) {
LOG_IF(FATAL, proxy_) << "Attempting to re-add a Proxy.";
proxy_ = CHECK_NOTNULL(proxy);
}
void HttpHandlerV2::GetEntries(evhttp_request* req) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
void HttpHandlerV2::GetProof(evhttp_request* req) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
void HttpHandlerV2::GetSTH(evhttp_request* req) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
void HttpHandlerV2::GetConsistency(evhttp_request* req) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
void HttpHandlerV2::BlockingGetEntries(evhttp_request* req, int64_t start,
int64_t end, bool include_scts) const {
return SendJsonError(event_base_, req, HTTP_NOTIMPLEMENTED,
"Not yet implemented.");
}
|