it complies and crow updated

This commit is contained in:
moneroexamples 2016-09-06 18:34:07 +08:00
parent 9b3a27baa9
commit f9925d6c3b
20 changed files with 870 additions and 513 deletions

View File

@ -31,11 +31,11 @@ find_package(Boost COMPONENTS
# set location of monero static libraries
set(MONERO_LIBS_DIR
/opt/bitmonero-dev/libs)
/opt/monero-dev/libs)
# set location of moneroheaders
set(MONERO_HEADERS_DIR
/opt/bitmonero-dev/headers)
/opt/monero-dev/headers)
# include monero headers
include_directories(
@ -50,21 +50,17 @@ include_directories(
add_library(common STATIC IMPORTED)
set_property(TARGET common PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libcommon.a)
add_library(blocks STATIC IMPORTED)
set_property(TARGET blocks PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libblocks.a)
add_library(crypto STATIC IMPORTED)
set_property(TARGET crypto
PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libcrypto.a)
add_library(cryptonote_core STATIC IMPORTED)
set_property(TARGET cryptonote_core
PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libcryptonote_core.a)
add_library(blockchain_db STATIC IMPORTED)
set_property(TARGET blockchain_db
PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libblockchain_db.a)
@ -73,6 +69,9 @@ add_library(lmdb STATIC IMPORTED)
set_property(TARGET lmdb
PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/liblmdb.a)
add_library(ringct STATIC IMPORTED)
set_property(TARGET ringct
PROPERTY IMPORTED_LOCATION ${MONERO_LIBS_DIR}/libringct.a)
# include boost headers
include_directories(${Boost_INCLUDE_DIRS})
@ -125,6 +124,7 @@ target_link_libraries(${PROJECT_NAME}
blocks
common
lmdb
ringct
${Boost_LIBRARIES}
pthread
unbound

49
ext/crow/common.h Normal file → Executable file
View File

@ -10,7 +10,8 @@ namespace crow
{
enum class HTTPMethod
{
DELETE,
#ifndef DELETE
DELETE = 0,
GET,
HEAD,
POST,
@ -18,27 +19,37 @@ namespace crow
CONNECT,
OPTIONS,
TRACE,
#endif
Delete = 0,
Get,
Head,
Post,
Put,
Connect,
Options,
Trace,
};
inline std::string method_name(HTTPMethod method)
{
switch(method)
{
case HTTPMethod::DELETE:
case HTTPMethod::Delete:
return "DELETE";
case HTTPMethod::GET:
case HTTPMethod::Get:
return "GET";
case HTTPMethod::HEAD:
case HTTPMethod::Head:
return "HEAD";
case HTTPMethod::POST:
case HTTPMethod::Post:
return "POST";
case HTTPMethod::PUT:
case HTTPMethod::Put:
return "PUT";
case HTTPMethod::CONNECT:
case HTTPMethod::Connect:
return "CONNECT";
case HTTPMethod::OPTIONS:
case HTTPMethod::Options:
return "OPTIONS";
case HTTPMethod::TRACE:
case HTTPMethod::Trace:
return "TRACE";
}
return "invalid";
@ -110,17 +121,17 @@ namespace crow
}
#ifndef CROW_MSVC_WORKAROUND
constexpr crow::HTTPMethod operator "" _method(const char* str, size_t len)
constexpr crow::HTTPMethod operator "" _method(const char* str, size_t /*len*/)
{
return
crow::black_magic::is_equ_p(str, "GET", 3) ? crow::HTTPMethod::GET :
crow::black_magic::is_equ_p(str, "DELETE", 6) ? crow::HTTPMethod::DELETE :
crow::black_magic::is_equ_p(str, "HEAD", 4) ? crow::HTTPMethod::HEAD :
crow::black_magic::is_equ_p(str, "POST", 4) ? crow::HTTPMethod::POST :
crow::black_magic::is_equ_p(str, "PUT", 3) ? crow::HTTPMethod::PUT :
crow::black_magic::is_equ_p(str, "OPTIONS", 7) ? crow::HTTPMethod::OPTIONS :
crow::black_magic::is_equ_p(str, "CONNECT", 7) ? crow::HTTPMethod::CONNECT :
crow::black_magic::is_equ_p(str, "TRACE", 5) ? crow::HTTPMethod::TRACE :
crow::black_magic::is_equ_p(str, "GET", 3) ? crow::HTTPMethod::Get :
crow::black_magic::is_equ_p(str, "DELETE", 6) ? crow::HTTPMethod::Delete :
crow::black_magic::is_equ_p(str, "HEAD", 4) ? crow::HTTPMethod::Head :
crow::black_magic::is_equ_p(str, "POST", 4) ? crow::HTTPMethod::Post :
crow::black_magic::is_equ_p(str, "PUT", 3) ? crow::HTTPMethod::Put :
crow::black_magic::is_equ_p(str, "OPTIONS", 7) ? crow::HTTPMethod::Options :
crow::black_magic::is_equ_p(str, "CONNECT", 7) ? crow::HTTPMethod::Connect :
crow::black_magic::is_equ_p(str, "TRACE", 5) ? crow::HTTPMethod::Trace :
throw std::runtime_error("invalid http method");
};
}
#endif

54
ext/crow/crow.h Normal file → Executable file
View File

@ -9,7 +9,7 @@
#include <thread>
#include "settings.h"
#include "logging.h"
#include "logging.h"
#include "utility.h"
#include "routing.h"
#include "middleware_context.h"
@ -41,6 +41,12 @@ namespace crow
{
}
template <typename Adaptor>
void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
{
router_.handle_upgrade(req, res, adaptor);
}
void handle(const request& req, response& res)
{
router_.handle(req, res);
@ -64,6 +70,12 @@ namespace crow
return *this;
}
self_t& bindaddr(std::string bindaddr)
{
bindaddr_ = bindaddr;
return *this;
}
self_t& multithreaded()
{
return concurrency(std::thread::hardware_concurrency());
@ -88,14 +100,28 @@ namespace crow
#ifdef CROW_ENABLE_SSL
if (use_ssl_)
{
ssl_server_t server(this, port_, &middlewares_, concurrency_, &ssl_context_);
server.run();
ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, &middlewares_, concurrency_, &ssl_context_)));
ssl_server_->run();
}
else
#endif
{
server_t server(this, port_, &middlewares_, concurrency_, nullptr);
server.run();
server_ = std::move(std::unique_ptr<server_t>(new server_t(this, bindaddr_, port_, &middlewares_, concurrency_, nullptr)));
server_->run();
}
}
void stop()
{
#ifdef CROW_ENABLE_SSL
if (use_ssl_)
{
ssl_server_->stop();
}
else
#endif
{
server_->stop();
}
}
@ -146,23 +172,23 @@ namespace crow
#else
template <typename T, typename ... Remain>
self_t& ssl_file(T&& t, Remain&&...)
self_t& ssl_file(T&&, Remain&&...)
{
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert(
// make static_assert dependent to T; always false
std::is_base_of<T, void>::value,
std::is_base_of<T, void>::value,
"Define CROW_ENABLE_SSL to enable ssl support.");
return *this;
}
template <typename T>
self_t& ssl(T&& ctx)
self_t& ssl(T&&)
{
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert(
// make static_assert dependent to T; always false
std::is_base_of<T, void>::value,
std::is_base_of<T, void>::value,
"Define CROW_ENABLE_SSL to enable ssl support.");
return *this;
}
@ -187,13 +213,17 @@ namespace crow
private:
uint16_t port_ = 80;
uint16_t concurrency_ = 1;
std::string bindaddr_ = "0.0.0.0";
Router router_;
std::tuple<Middlewares...> middlewares_;
#ifdef CROW_ENABLE_SSL
std::unique_ptr<ssl_server_t> ssl_server_;
#endif
std::unique_ptr<server_t> server_;
};
template <typename ... Middlewares>
using App = Crow<Middlewares...>;
using SimpleApp = Crow<>;
};
}

32
ext/crow/http_connection.h Normal file → Executable file
View File

@ -98,28 +98,28 @@ namespace crow
template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<!is_before_handle_arity_3_impl<MW>::value>::type
before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& parent_ctx)
before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
{
mw.before_handle(req, res, ctx.template get<MW>(), ctx);
}
template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<is_before_handle_arity_3_impl<MW>::value>::type
before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& parent_ctx)
before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
{
mw.before_handle(req, res, ctx.template get<MW>());
}
template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<!is_after_handle_arity_3_impl<MW>::value>::type
after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& parent_ctx)
after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
{
mw.after_handle(req, res, ctx.template get<MW>(), ctx);
}
template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<is_after_handle_arity_3_impl<MW>::value>::type
after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& parent_ctx)
after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
{
mw.after_handle(req, res, ctx.template get<MW>());
}
@ -146,14 +146,14 @@ namespace crow
}
template <int N, typename Context, typename Container>
bool middleware_call_helper(Container& middlewares, request& req, response& res, Context& ctx)
bool middleware_call_helper(Container& /*middlewares*/, request& /*req*/, response& /*res*/, Context& /*ctx*/)
{
return false;
}
template <int N, typename Context, typename Container>
typename std::enable_if<(N<0)>::type
after_handlers_call_helper(Container& middlewares, Context& context, request& req, response& res)
after_handlers_call_helper(Container& /*middlewares*/, Context& /*context*/, request& /*req*/, response& /*res*/)
{
}
@ -256,6 +256,7 @@ namespace crow
req_ = std::move(parser_.to_request());
request& req = req_;
if (parser_.check_version(1, 0))
{
// HTTP/1.0
@ -282,6 +283,20 @@ namespace crow
is_invalid_request = true;
res = response(400);
}
if (parser_.is_upgrade())
{
if (req.get_header_value("upgrade") == "h2c")
{
// TODO HTTP/2
// currently, ignore upgrade header
}
else
{
close_connection_ = true;
handler_->handle_upgrade(req, res, std::move(adaptor_));
return;
}
}
}
CROW_LOG_INFO << "Request: " << boost::lexical_cast<std::string>(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << parser_.http_major << "." << parser_.http_minor << ' '
@ -296,6 +311,7 @@ namespace crow
ctx_ = detail::context<Middlewares...>();
req.middleware_context = (void*)&ctx_;
req.io_service = &adaptor_.get_io_service();
detail::middleware_call_helper<0, decltype(ctx_), decltype(*middlewares_), Middlewares...>(*middlewares_, req, res, ctx_);
if (!res.completed_)
@ -484,7 +500,7 @@ namespace crow
//auto self = this->shared_from_this();
is_writing = true;
boost::asio::async_write(adaptor_.socket(), buffers_,
[&](const boost::system::error_code& ec, std::size_t bytes_transferred)
[&](const boost::system::error_code& ec, std::size_t /*bytes_transferred*/)
{
is_writing = false;
res.clear();
@ -522,7 +538,7 @@ namespace crow
timer_queue.cancel(timer_cancel_key_);
}
void start_deadline(int timeout = 5)
void start_deadline(/*int timeout = 5*/)
{
cancel_deadline_timer();

804
ext/crow/http_parser_merged.h Normal file → Executable file

File diff suppressed because it is too large Load Diff

18
ext/crow/http_request.h Normal file → Executable file
View File

@ -3,6 +3,7 @@
#include "common.h"
#include "ci_map.h"
#include "query_string.h"
#include <boost/asio.hpp>
namespace crow
{
@ -17,6 +18,8 @@ namespace crow
return empty;
}
struct DetachHelper;
struct request
{
HTTPMethod method;
@ -27,9 +30,10 @@ namespace crow
std::string body;
void* middleware_context{};
boost::asio::io_service* io_service{};
request()
: method(HTTPMethod::GET)
: method(HTTPMethod::Get)
{
}
@ -48,5 +52,17 @@ namespace crow
return crow::get_header_value(headers, key);
}
template<typename CompletionHandler>
void post(CompletionHandler handler)
{
io_service->post(handler);
}
template<typename CompletionHandler>
void dispatch(CompletionHandler handler)
{
io_service->dispatch(handler);
}
};
}

14
ext/crow/http_response.h Normal file → Executable file
View File

@ -14,9 +14,9 @@ namespace crow
template <typename Adaptor, typename Handler, typename ... Middlewares>
friend class crow::Connection;
int code{200};
std::string body;
json::wvalue json_value;
int code{200};
// `headers' stores HTTP headers.
ci_map headers;
@ -40,12 +40,12 @@ namespace crow
response() {}
explicit response(int code) : code(code) {}
response(std::string body) : body(std::move(body)) {}
response(json::wvalue&& json_value) : json_value(std::move(json_value))
response(json::wvalue&& json_value) : json_value(std::move(json_value))
{
json_mode();
json_mode();
}
response(int code, std::string body) : body(std::move(body)), code(code) {}
response(const json::wvalue& json_value) : body(json::dump(json_value))
response(int code, std::string body) : code(code), body(std::move(body)) {}
response(const json::wvalue& json_value) : body(json::dump(json_value))
{
json_mode();
}
@ -95,7 +95,7 @@ namespace crow
if (!completed_)
{
completed_ = true;
if (complete_request_handler_)
{
complete_request_handler_();
@ -118,7 +118,7 @@ namespace crow
bool completed_{};
std::function<void()> complete_request_handler_;
std::function<bool()> is_alive_helper_;
//In case of a JSON object, set the Content-Type header
void json_mode()
{

33
ext/crow/http_server.h Normal file → Executable file
View File

@ -20,17 +20,18 @@ namespace crow
{
using namespace boost;
using tcp = asio::ip::tcp;
template <typename Handler, typename Adaptor = SocketAdaptor, typename ... Middlewares>
class Server
{
public:
Server(Handler* handler, uint16_t port, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr)
: acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)),
Server(Handler* handler, std::string bindaddr, uint16_t port, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr)
: acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string(bindaddr), port)),
signals_(io_service_, SIGINT, SIGTERM),
handler_(handler),
handler_(handler),
concurrency_(concurrency),
port_(port),
bindaddr_(bindaddr),
middlewares_(middlewares),
adaptor_ctx_(adaptor_ctx)
{
@ -47,9 +48,10 @@ namespace crow
timer_queue_pool_.resize(concurrency_);
std::vector<std::future<void>> v;
std::atomic<int> init_count(0);
for(uint16_t i = 0; i < concurrency_; i ++)
v.push_back(
std::async(std::launch::async, [this, i]{
std::async(std::launch::async, [this, i, &init_count]{
// thread local date string get function
auto last = std::chrono::steady_clock::now();
@ -98,20 +100,24 @@ namespace crow
};
timer.async_wait(handler);
io_service_pool_[i]->run();
init_count ++;
try
{
io_service_pool_[i]->run();
} catch(std::exception& e)
{
CROW_LOG_ERROR << "Worker Crash: An uncaught exception occurred: " << e.what();
}
}));
CROW_LOG_INFO << server_name_ << " server is running, local port " << port_;
signals_.async_wait(
[&](const boost::system::error_code& error, int signal_number){
[&](const boost::system::error_code& /*error*/, int /*signal_number*/){
stop();
});
for (int i = 0; i < concurrency_; i++)
{
while (timer_queue_pool_[i] == nullptr)
std::this_thread::yield();
}
while(concurrency_ != init_count)
std::this_thread::yield();
do_accept();
@ -145,7 +151,7 @@ namespace crow
is, handler_, server_name_, middlewares_,
get_cached_date_str_pool_[roundrobin_index_], *timer_queue_pool_[roundrobin_index_],
adaptor_ctx_);
acceptor_.async_accept(p->socket(),
acceptor_.async_accept(p->socket(),
[this, p, &is](boost::system::error_code ec)
{
if (!ec)
@ -171,6 +177,7 @@ namespace crow
uint16_t concurrency_{1};
std::string server_name_ = "Crow/0.1";
uint16_t port_;
std::string bindaddr_;
unsigned int roundrobin_index_{};
std::tuple<Middlewares...>* middlewares_;

51
ext/crow/json.h Normal file → Executable file
View File

@ -82,7 +82,7 @@ namespace crow
Object,
};
const char* get_type_str(type t) {
inline const char* get_type_str(type t) {
switch(t){
case type::Number: return "Number";
case type::False: return "False";
@ -92,7 +92,7 @@ namespace crow
case type::Object: return "Object";
default: return "Unknown";
}
};
}
class rvalue;
rvalue load(const char* data, size_t size);
@ -131,6 +131,8 @@ namespace crow
s_ = r.s_;
e_ = r.e_;
owned_ = r.owned_;
if (r.owned_)
r.owned_ = 0;
return *this;
}
@ -164,7 +166,7 @@ namespace crow
return os;
}
private:
void force(char* s, uint32_t length)
void force(char* s, uint32_t /*length*/)
{
s_ = s;
owned_ = 1;
@ -262,6 +264,11 @@ namespace crow
return i();
}
explicit operator uint64_t() const
{
return u();
}
explicit operator int() const
{
return (int)i();
@ -286,14 +293,28 @@ namespace crow
case type::String:
return boost::lexical_cast<int64_t>(start_, end_-start_);
default:
throw std::runtime_error(
"expected number, got: " + std::string(get_type_str(t()))
);
const std::string msg = "expected number, got: "
+ std::string(get_type_str(t()));
throw std::runtime_error(msg);
}
#endif
return boost::lexical_cast<int64_t>(start_, end_-start_);
}
uint64_t u() const
{
#ifndef CROW_JSON_NO_ERROR_CHECK
switch (t()) {
case type::Number:
case type::String:
return boost::lexical_cast<uint64_t>(start_, end_-start_);
default:
throw std::runtime_error(std::string("expected number, got: ") + get_type_str(t()));
}
#endif
return boost::lexical_cast<uint64_t>(start_, end_-start_);
}
double d() const
{
#ifndef CROW_JSON_NO_ERROR_CHECK
@ -671,7 +692,7 @@ namespace crow
//static const char* escaped = "\"\\/\b\f\n\r\t";
struct Parser
{
Parser(char* data, size_t size)
Parser(char* data, size_t /*size*/)
: data(data)
{
}
@ -1093,17 +1114,16 @@ namespace crow
s = r.s();
return;
case type::List:
l = std::move(std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{}));
l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
l->reserve(r.size());
for(auto it = r.begin(); it != r.end(); ++it)
l->emplace_back(*it);
return;
case type::Object:
o = std::move(
std::unique_ptr<
o = std::unique_ptr<
std::unordered_map<std::string, wvalue>
>(
new std::unordered_map<std::string, wvalue>{}));
new std::unordered_map<std::string, wvalue>{});
for(auto it = r.begin(); it != r.end(); ++it)
o->emplace(it->key(), *it);
return;
@ -1249,7 +1269,7 @@ namespace crow
reset();
t_ = type::List;
if (!l)
l = std::move(std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{}));
l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
l->clear();
l->resize(v.size());
size_t idx = 0;
@ -1266,7 +1286,7 @@ namespace crow
reset();
t_ = type::List;
if (!l)
l = std::move(std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{}));
l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
if (l->size() < index+1)
l->resize(index+1);
return (*l)[index];
@ -1287,11 +1307,10 @@ namespace crow
reset();
t_ = type::Object;
if (!o)
o = std::move(
std::unique_ptr<
o = std::unique_ptr<
std::unordered_map<std::string, wvalue>
>(
new std::unordered_map<std::string, wvalue>{}));
new std::unordered_map<std::string, wvalue>{});
return (*o)[str];
}

32
ext/crow/logging.h Normal file → Executable file
View File

@ -13,11 +13,19 @@ namespace crow
{
enum class LogLevel
{
DEBUG,
#ifndef ERROR
DEBUG = 0,
INFO,
WARNING,
ERROR,
CRITICAL,
#endif
Debug = 0,
Info,
Warning,
Error,
Critical,
};
class ILogHandler {
@ -27,7 +35,7 @@ namespace crow
class CerrLogHandler : public ILogHandler {
public:
void log(std::string message, LogLevel level) override {
void log(std::string message, LogLevel /*level*/) override {
std::cerr << message;
}
};
@ -117,18 +125,18 @@ namespace crow
}
#define CROW_LOG_CRITICAL \
if (crow::logger::get_current_log_level() <= crow::LogLevel::CRITICAL) \
crow::logger("CRITICAL", crow::LogLevel::CRITICAL)
if (crow::logger::get_current_log_level() <= crow::LogLevel::Critical) \
crow::logger("CRITICAL", crow::LogLevel::Critical)
#define CROW_LOG_ERROR \
if (crow::logger::get_current_log_level() <= crow::LogLevel::ERROR) \
crow::logger("ERROR ", crow::LogLevel::ERROR)
if (crow::logger::get_current_log_level() <= crow::LogLevel::Error) \
crow::logger("ERROR ", crow::LogLevel::Error)
#define CROW_LOG_WARNING \
if (crow::logger::get_current_log_level() <= crow::LogLevel::WARNING) \
crow::logger("WARNING ", crow::LogLevel::WARNING)
if (crow::logger::get_current_log_level() <= crow::LogLevel::Warning) \
crow::logger("WARNING ", crow::LogLevel::Warning)
#define CROW_LOG_INFO \
if (crow::logger::get_current_log_level() <= crow::LogLevel::INFO) \
crow::logger("INFO ", crow::LogLevel::INFO)
if (crow::logger::get_current_log_level() <= crow::LogLevel::Info) \
crow::logger("INFO ", crow::LogLevel::Info)
#define CROW_LOG_DEBUG \
if (crow::logger::get_current_log_level() <= crow::LogLevel::DEBUG) \
crow::logger("DEBUG ", crow::LogLevel::DEBUG)
if (crow::logger::get_current_log_level() <= crow::LogLevel::Debug) \
crow::logger("DEBUG ", crow::LogLevel::Debug)

2
ext/crow/middleware.h Normal file → Executable file
View File

@ -139,7 +139,7 @@ namespace crow
}
}
void after_handle(request& req, response& res, context& ctx)
void after_handle(request& /*req*/, response& res, context& ctx)
{
for(auto& cookie:ctx.cookies_to_add)
{

6
ext/crow/mustache.h Normal file → Executable file
View File

@ -520,7 +520,11 @@ namespace crow
inline std::string default_loader(const std::string& filename)
{
std::ifstream inf(detail::get_template_base_directory_ref() + filename);
std::string path = detail::get_template_base_directory_ref();
if (!(path.back() == '/' || path.back() == '\\'))
path += '/';
path += filename;
std::ifstream inf(path);
if (!inf)
return {};
return {std::istreambuf_iterator<char>(inf), std::istreambuf_iterator<char>()};

5
ext/crow/parser.h Normal file → Executable file
View File

@ -143,6 +143,11 @@ namespace crow
return request{(HTTPMethod)method, std::move(raw_url), std::move(url), std::move(url_params), std::move(headers), std::move(body)};
}
bool is_upgrade() const
{
return upgrade;
}
bool check_version(int major, int minor) const
{
return http_major == major && http_minor == minor;

169
ext/crow/routing.h Normal file → Executable file
View File

@ -13,6 +13,7 @@
#include "http_request.h"
#include "utility.h"
#include "logging.h"
#include "websocket.h"
namespace crow
{
@ -29,8 +30,26 @@ namespace crow
}
virtual void validate() = 0;
std::unique_ptr<BaseRule> upgrade()
{
if (rule_to_upgrade_)
return std::move(rule_to_upgrade_);
return {};
}
virtual void handle(const request&, response&, const routing_params&) = 0;
virtual void handle_upgrade(const request&, response& res, SocketAdaptor&&)
{
res = response(404);
res.end();
}
#ifdef CROW_ENABLE_SSL
virtual void handle_upgrade(const request&, response& res, SSLAdaptor&&)
{
res = response(404);
res.end();
}
#endif
uint32_t get_methods()
{
@ -38,10 +57,13 @@ namespace crow
}
protected:
uint32_t methods_{1<<(int)HTTPMethod::GET};
uint32_t methods_{1<<(int)HTTPMethod::Get};
std::string rule_;
std::string name_;
std::unique_ptr<BaseRule> rule_to_upgrade_;
friend class Router;
template <typename T>
friend struct RuleParameterTraits;
@ -233,10 +255,82 @@ namespace crow
}
}
class WebSocketRule : public BaseRule
{
using self_t = WebSocketRule;
public:
WebSocketRule(std::string rule)
: BaseRule(std::move(rule))
{
}
void validate() override
{
}
void handle(const request&, response& res, const routing_params&) override
{
res = response(404);
res.end();
}
void handle_upgrade(const request& req, response&, SocketAdaptor&& adaptor) override
{
new crow::websocket::Connection<SocketAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_);
}
#ifdef CROW_ENABLE_SSL
void handle_upgrade(const request& req, response&, SSLAdaptor&& adaptor) override
{
new crow::websocket::Connection<SSLAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_);
}
#endif
template <typename Func>
self_t& onopen(Func f)
{
open_handler_ = f;
return *this;
}
template <typename Func>
self_t& onmessage(Func f)
{
message_handler_ = f;
return *this;
}
template <typename Func>
self_t& onclose(Func f)
{
close_handler_ = f;
return *this;
}
template <typename Func>
self_t& onerror(Func f)
{
error_handler_ = f;
return *this;
}
protected:
std::function<void(crow::websocket::connection&)> open_handler_;
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
std::function<void(crow::websocket::connection&)> error_handler_;
};
template <typename T>
struct RuleParameterTraits
{
using self_t = T;
WebSocketRule& websocket()
{
auto p =new WebSocketRule(((self_t*)this)->rule_);
((self_t*)this)->rule_to_upgrade_.reset(p);
return *p;
}
self_t& name(std::string name) noexcept
{
((self_t*)this)->name_ = std::move(name);
@ -256,6 +350,7 @@ namespace crow
((self_t*)this)->methods_ |= 1 << (int)method;
return (self_t&)*this;
}
};
class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
@ -343,7 +438,7 @@ namespace crow
{
}
void validate()
void validate() override
{
if (!handler_)
{
@ -809,10 +904,80 @@ public:
for(auto& rule:rules_)
{
if (rule)
{
auto upgraded = rule->upgrade();
if (upgraded)
rule = std::move(upgraded);
rule->validate();
}
}
}
template <typename Adaptor>
void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
{
auto found = trie_.find(req.url);
unsigned rule_index = found.first;
if (!rule_index)
{
CROW_LOG_DEBUG << "Cannot match rules " << req.url;
res = response(404);
res.end();
return;
}
if (rule_index >= rules_.size())
throw std::runtime_error("Trie internal structure corrupted!");
if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
{
CROW_LOG_INFO << "Redirecting to a url with trailing slash: " << req.url;
res = response(301);
// TODO absolute url building
if (req.get_header_value("Host").empty())
{
res.add_header("Location", req.url + "/");
}
else
{
res.add_header("Location", "http://" + req.get_header_value("Host") + req.url + "/");
}
res.end();
return;
}
if ((rules_[rule_index]->get_methods() & (1<<(uint32_t)req.method)) == 0)
{
CROW_LOG_DEBUG << "Rule found but method mismatch: " << req.url << " with " << method_name(req.method) << "(" << (uint32_t)req.method << ") / " << rules_[rule_index]->get_methods();
res = response(404);
res.end();
return;
}
CROW_LOG_DEBUG << "Matched rule (upgrade) '" << rules_[rule_index]->rule_ << "' " << (uint32_t)req.method << " / " << rules_[rule_index]->get_methods();
// any uncaught exceptions become 500s
try
{
rules_[rule_index]->handle_upgrade(req, res, std::move(adaptor));
}
catch(std::exception& e)
{
CROW_LOG_ERROR << "An uncaught exception occurred: " << e.what();
res = response(500);
res.end();
return;
}
catch(...)
{
CROW_LOG_ERROR << "An uncaught exception occurred. The type was unknown so no information was available.";
res = response(500);
res.end();
return;
}
}
void handle(const request& req, response& res)
{
auto found = trie_.find(req.url);

24
ext/crow/socket_adaptors.h Normal file → Executable file
View File

@ -1,5 +1,8 @@
#pragma once
#include <boost/asio.hpp>
#ifdef CROW_ENABLE_SSL
#include <boost/asio/ssl.hpp>
#endif
#include "settings.h"
namespace crow
{
@ -14,6 +17,11 @@ namespace crow
{
}
boost::asio::io_service& get_io_service()
{
return socket_.get_io_service();
}
tcp::socket& raw_socket()
{
return socket_;
@ -52,20 +60,21 @@ namespace crow
struct SSLAdaptor
{
using context = boost::asio::ssl::context;
using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
SSLAdaptor(boost::asio::io_service& io_service, context* ctx)
: ssl_socket_(io_service, *ctx)
: ssl_socket_(new ssl_socket_t(io_service, *ctx))
{
}
boost::asio::ssl::stream<tcp::socket>& socket()
{
return ssl_socket_;
return *ssl_socket_;
}
tcp::socket::lowest_layer_type&
raw_socket()
{
return ssl_socket_.lowest_layer();
return ssl_socket_->lowest_layer();
}
tcp::endpoint remote_endpoint()
@ -83,16 +92,21 @@ namespace crow
raw_socket().close();
}
boost::asio::io_service& get_io_service()
{
return raw_socket().get_io_service();
}
template <typename F>
void start(F f)
{
ssl_socket_.async_handshake(boost::asio::ssl::stream_base::server,
ssl_socket_->async_handshake(boost::asio::ssl::stream_base::server,
[f](const boost::system::error_code& ec) {
f(ec);
});
}
boost::asio::ssl::stream<tcp::socket> ssl_socket_;
std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> ssl_socket_;
};
#endif
}

47
ext/crow/utility.h Normal file → Executable file
View File

@ -6,6 +6,7 @@
#include <type_traits>
#include <cstring>
#include <functional>
#include <string>
namespace crow
{
@ -14,7 +15,7 @@ namespace crow
#ifndef CROW_MSVC_WORKAROUND
struct OutOfRange
{
OutOfRange(unsigned pos, unsigned length) {}
OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
};
constexpr unsigned requires_in_range( unsigned i, unsigned len )
{
@ -129,7 +130,7 @@ template <> \
struct parameter_tag<t> \
{ \
static const int value = i; \
};
}
CROW_INTERNAL_PARAMETER_TAG(int, 1);
CROW_INTERNAL_PARAMETER_TAG(char, 1);
CROW_INTERNAL_PARAMETER_TAG(short, 1);
@ -499,5 +500,47 @@ template <typename F, typename Set>
using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
std::string base64encode(const char* data, size_t size, const char* key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
{
std::string ret;
ret.resize((size+2) / 3 * 4);
auto it = ret.begin();
while(size >= 3)
{
*it++ = key[(((unsigned char)*data)&0xFC)>>2];
unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
*it++ = key[h|((((unsigned char)*data)&0xF0)>>4)];
h = (((unsigned char)*data++) & 0x0F) << 2;
*it++ = key[h|((((unsigned char)*data)&0xC0)>>6)];
*it++ = key[((unsigned char)*data++)&0x3F];
size -= 3;
}
if (size == 1)
{
*it++ = key[(((unsigned char)*data)&0xFC)>>2];
unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
*it++ = key[h];
*it++ = '=';
*it++ = '=';
}
else if (size == 2)
{
*it++ = key[(((unsigned char)*data)&0xFC)>>2];
unsigned char h = (((unsigned char)*data++) & 0x03) << 4;
*it++ = key[h|((((unsigned char)*data)&0xF0)>>4)];
h = (((unsigned char)*data++) & 0x0F) << 2;
*it++ = key[h];
*it++ = '=';
}
return ret;
}
std::string base64encode_urlsafe(const char* data, size_t size)
{
return base64encode(data, size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
}
} // namespace utility
}

View File

@ -1,9 +1,11 @@
#include "ext/crow/crow.h"
#include "src/CmdLineOptions.h"
#include "src/MicroCore.h"
#include "src/page.h"
#include "ext/crow/crow.h"
#include "ext/member_checker.h"
#include <fstream>

View File

@ -4,6 +4,17 @@
#include "MicroCore.h"
namespace
{
// NOTE: These values should match blockchain.cpp
// TODO: Refactor
const uint64_t mainnet_hard_fork_version_1_till = 1009826;
const uint64_t testnet_hard_fork_version_1_till = 624633;
}
namespace xmreg
{
/**
@ -46,8 +57,16 @@ namespace xmreg
//db_flags = DEFAULT_FLAGS;
HardFork* m_hardfork = nullptr;
BlockchainDB* db = nullptr;
db = new BlockchainLMDB();
db = new BlockchainLMDB();
bool use_testnet {false};
uint64_t hard_fork_version_1_till = use_testnet ? testnet_hard_fork_version_1_till : mainnet_hard_fork_version_1_till;
m_hardfork = new HardFork(*db, 1, hard_fork_version_1_till);
try
{
@ -69,7 +88,7 @@ namespace xmreg
// initialize Blockchain object to manage
// the database.
return m_blockchain_storage.init(db, false);
return m_blockchain_storage.init(db, m_hardfork, false);
}
/**

View File

@ -11,7 +11,6 @@
#include "tx_details.h"
namespace xmreg
{
using namespace cryptonote;

View File

@ -15,9 +15,8 @@
#include "storages/http_abstract_invoke.h"
#include "cryptonote_core/cryptonote_basic.h"
#include "cryptonote_core/blockchain_storage.h"
#include "cryptonote_core/tx_pool.h"
#include "cryptonote_core/blockchain.h"
#include "blockchain_db/lmdb/db_lmdb.h"