it complies and crow updated

master
moneroexamples 8 years ago
parent 9b3a27baa9
commit f9925d6c3b

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

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

@ -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) void handle(const request& req, response& res)
{ {
router_.handle(req, res); router_.handle(req, res);
@ -64,6 +70,12 @@ namespace crow
return *this; return *this;
} }
self_t& bindaddr(std::string bindaddr)
{
bindaddr_ = bindaddr;
return *this;
}
self_t& multithreaded() self_t& multithreaded()
{ {
return concurrency(std::thread::hardware_concurrency()); return concurrency(std::thread::hardware_concurrency());
@ -88,14 +100,28 @@ namespace crow
#ifdef CROW_ENABLE_SSL #ifdef CROW_ENABLE_SSL
if (use_ssl_) if (use_ssl_)
{ {
ssl_server_t server(this, port_, &middlewares_, concurrency_, &ssl_context_); ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, &middlewares_, concurrency_, &ssl_context_)));
server.run(); ssl_server_->run();
} }
else else
#endif #endif
{ {
server_t server(this, port_, &middlewares_, concurrency_, nullptr); server_ = std::move(std::unique_ptr<server_t>(new server_t(this, bindaddr_, port_, &middlewares_, concurrency_, nullptr)));
server.run(); server_->run();
}
}
void stop()
{
#ifdef CROW_ENABLE_SSL
if (use_ssl_)
{
ssl_server_->stop();
}
else
#endif
{
server_->stop();
} }
} }
@ -146,7 +172,7 @@ namespace crow
#else #else
template <typename T, typename ... Remain> 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. // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert( static_assert(
@ -157,7 +183,7 @@ namespace crow
} }
template <typename T> 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. // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
static_assert( static_assert(
@ -187,13 +213,17 @@ namespace crow
private: private:
uint16_t port_ = 80; uint16_t port_ = 80;
uint16_t concurrency_ = 1; uint16_t concurrency_ = 1;
std::string bindaddr_ = "0.0.0.0";
Router router_; Router router_;
std::tuple<Middlewares...> middlewares_; 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> template <typename ... Middlewares>
using App = Crow<Middlewares...>; using App = Crow<Middlewares...>;
using SimpleApp = Crow<>; using SimpleApp = Crow<>;
}; }

@ -98,28 +98,28 @@ namespace crow
template <typename MW, typename Context, typename ParentContext> template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<!is_before_handle_arity_3_impl<MW>::value>::type 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); mw.before_handle(req, res, ctx.template get<MW>(), ctx);
} }
template <typename MW, typename Context, typename ParentContext> template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<is_before_handle_arity_3_impl<MW>::value>::type 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>()); mw.before_handle(req, res, ctx.template get<MW>());
} }
template <typename MW, typename Context, typename ParentContext> template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<!is_after_handle_arity_3_impl<MW>::value>::type 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); mw.after_handle(req, res, ctx.template get<MW>(), ctx);
} }
template <typename MW, typename Context, typename ParentContext> template <typename MW, typename Context, typename ParentContext>
typename std::enable_if<is_after_handle_arity_3_impl<MW>::value>::type 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>()); mw.after_handle(req, res, ctx.template get<MW>());
} }
@ -146,14 +146,14 @@ namespace crow
} }
template <int N, typename Context, typename Container> 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; return false;
} }
template <int N, typename Context, typename Container> template <int N, typename Context, typename Container>
typename std::enable_if<(N<0)>::type 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()); req_ = std::move(parser_.to_request());
request& req = req_; request& req = req_;
if (parser_.check_version(1, 0)) if (parser_.check_version(1, 0))
{ {
// HTTP/1.0 // HTTP/1.0
@ -282,6 +283,20 @@ namespace crow
is_invalid_request = true; is_invalid_request = true;
res = response(400); 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 << ' ' 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...>(); ctx_ = detail::context<Middlewares...>();
req.middleware_context = (void*)&ctx_; 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_); detail::middleware_call_helper<0, decltype(ctx_), decltype(*middlewares_), Middlewares...>(*middlewares_, req, res, ctx_);
if (!res.completed_) if (!res.completed_)
@ -484,7 +500,7 @@ namespace crow
//auto self = this->shared_from_this(); //auto self = this->shared_from_this();
is_writing = true; is_writing = true;
boost::asio::async_write(adaptor_.socket(), buffers_, 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; is_writing = false;
res.clear(); res.clear();
@ -522,7 +538,7 @@ namespace crow
timer_queue.cancel(timer_cancel_key_); timer_queue.cancel(timer_cancel_key_);
} }
void start_deadline(int timeout = 5) void start_deadline(/*int timeout = 5*/)
{ {
cancel_deadline_timer(); cancel_deadline_timer();

File diff suppressed because it is too large Load Diff

@ -3,6 +3,7 @@
#include "common.h" #include "common.h"
#include "ci_map.h" #include "ci_map.h"
#include "query_string.h" #include "query_string.h"
#include <boost/asio.hpp>
namespace crow namespace crow
{ {
@ -17,6 +18,8 @@ namespace crow
return empty; return empty;
} }
struct DetachHelper;
struct request struct request
{ {
HTTPMethod method; HTTPMethod method;
@ -27,9 +30,10 @@ namespace crow
std::string body; std::string body;
void* middleware_context{}; void* middleware_context{};
boost::asio::io_service* io_service{};
request() request()
: method(HTTPMethod::GET) : method(HTTPMethod::Get)
{ {
} }
@ -48,5 +52,17 @@ namespace crow
return crow::get_header_value(headers, key); 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,9 +14,9 @@ namespace crow
template <typename Adaptor, typename Handler, typename ... Middlewares> template <typename Adaptor, typename Handler, typename ... Middlewares>
friend class crow::Connection; friend class crow::Connection;
int code{200};
std::string body; std::string body;
json::wvalue json_value; json::wvalue json_value;
int code{200};
// `headers' stores HTTP headers. // `headers' stores HTTP headers.
ci_map headers; ci_map headers;
@ -44,7 +44,7 @@ namespace crow
{ {
json_mode(); json_mode();
} }
response(int code, std::string body) : body(std::move(body)), code(code) {} response(int code, std::string body) : code(code), body(std::move(body)) {}
response(const json::wvalue& json_value) : body(json::dump(json_value)) response(const json::wvalue& json_value) : body(json::dump(json_value))
{ {
json_mode(); json_mode();

@ -25,12 +25,13 @@ namespace crow
class Server class Server
{ {
public: public:
Server(Handler* handler, uint16_t port, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr) 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(asio::ip::address(), port)), : acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string(bindaddr), port)),
signals_(io_service_, SIGINT, SIGTERM), signals_(io_service_, SIGINT, SIGTERM),
handler_(handler), handler_(handler),
concurrency_(concurrency), concurrency_(concurrency),
port_(port), port_(port),
bindaddr_(bindaddr),
middlewares_(middlewares), middlewares_(middlewares),
adaptor_ctx_(adaptor_ctx) adaptor_ctx_(adaptor_ctx)
{ {
@ -47,9 +48,10 @@ namespace crow
timer_queue_pool_.resize(concurrency_); timer_queue_pool_.resize(concurrency_);
std::vector<std::future<void>> v; std::vector<std::future<void>> v;
std::atomic<int> init_count(0);
for(uint16_t i = 0; i < concurrency_; i ++) for(uint16_t i = 0; i < concurrency_; i ++)
v.push_back( 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 // thread local date string get function
auto last = std::chrono::steady_clock::now(); auto last = std::chrono::steady_clock::now();
@ -98,20 +100,24 @@ namespace crow
}; };
timer.async_wait(handler); 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_; CROW_LOG_INFO << server_name_ << " server is running, local port " << port_;
signals_.async_wait( signals_.async_wait(
[&](const boost::system::error_code& error, int signal_number){ [&](const boost::system::error_code& /*error*/, int /*signal_number*/){
stop(); stop();
}); });
for (int i = 0; i < concurrency_; i++) while(concurrency_ != init_count)
{ std::this_thread::yield();
while (timer_queue_pool_[i] == nullptr)
std::this_thread::yield();
}
do_accept(); do_accept();
@ -171,6 +177,7 @@ namespace crow
uint16_t concurrency_{1}; uint16_t concurrency_{1};
std::string server_name_ = "Crow/0.1"; std::string server_name_ = "Crow/0.1";
uint16_t port_; uint16_t port_;
std::string bindaddr_;
unsigned int roundrobin_index_{}; unsigned int roundrobin_index_{};
std::tuple<Middlewares...>* middlewares_; std::tuple<Middlewares...>* middlewares_;

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

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

@ -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) for(auto& cookie:ctx.cookies_to_add)
{ {

@ -520,7 +520,11 @@ namespace crow
inline std::string default_loader(const std::string& filename) 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) if (!inf)
return {}; return {};
return {std::istreambuf_iterator<char>(inf), std::istreambuf_iterator<char>()}; return {std::istreambuf_iterator<char>(inf), std::istreambuf_iterator<char>()};

@ -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)}; 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 bool check_version(int major, int minor) const
{ {
return http_major == major && http_minor == minor; return http_major == major && http_minor == minor;

@ -13,6 +13,7 @@
#include "http_request.h" #include "http_request.h"
#include "utility.h" #include "utility.h"
#include "logging.h" #include "logging.h"
#include "websocket.h"
namespace crow namespace crow
{ {
@ -29,8 +30,26 @@ namespace crow
} }
virtual void validate() = 0; 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(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() uint32_t get_methods()
{ {
@ -38,10 +57,13 @@ namespace crow
} }
protected: protected:
uint32_t methods_{1<<(int)HTTPMethod::GET}; uint32_t methods_{1<<(int)HTTPMethod::Get};
std::string rule_; std::string rule_;
std::string name_; std::string name_;
std::unique_ptr<BaseRule> rule_to_upgrade_;
friend class Router; friend class Router;
template <typename T> template <typename T>
friend struct RuleParameterTraits; 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> template <typename T>
struct RuleParameterTraits struct RuleParameterTraits
{ {
using self_t = T; 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& name(std::string name) noexcept
{ {
((self_t*)this)->name_ = std::move(name); ((self_t*)this)->name_ = std::move(name);
@ -256,6 +350,7 @@ namespace crow
((self_t*)this)->methods_ |= 1 << (int)method; ((self_t*)this)->methods_ |= 1 << (int)method;
return (self_t&)*this; return (self_t&)*this;
} }
}; };
class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
@ -343,7 +438,7 @@ namespace crow
{ {
} }
void validate() void validate() override
{ {
if (!handler_) if (!handler_)
{ {
@ -809,10 +904,80 @@ public:
for(auto& rule:rules_) for(auto& rule:rules_)
{ {
if (rule) if (rule)
{
auto upgraded = rule->upgrade();
if (upgraded)
rule = std::move(upgraded);
rule->validate(); 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) void handle(const request& req, response& res)
{ {
auto found = trie_.find(req.url); auto found = trie_.find(req.url);

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

@ -6,6 +6,7 @@
#include <type_traits> #include <type_traits>
#include <cstring> #include <cstring>
#include <functional> #include <functional>
#include <string>
namespace crow namespace crow
{ {
@ -14,7 +15,7 @@ namespace crow
#ifndef CROW_MSVC_WORKAROUND #ifndef CROW_MSVC_WORKAROUND
struct OutOfRange struct OutOfRange
{ {
OutOfRange(unsigned pos, unsigned length) {} OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
}; };
constexpr unsigned requires_in_range( unsigned i, unsigned len ) constexpr unsigned requires_in_range( unsigned i, unsigned len )
{ {
@ -129,7 +130,7 @@ template <> \
struct parameter_tag<t> \ struct parameter_tag<t> \
{ \ { \
static const int value = i; \ static const int value = i; \
}; }
CROW_INTERNAL_PARAMETER_TAG(int, 1); CROW_INTERNAL_PARAMETER_TAG(int, 1);
CROW_INTERNAL_PARAMETER_TAG(char, 1); CROW_INTERNAL_PARAMETER_TAG(char, 1);
CROW_INTERNAL_PARAMETER_TAG(short, 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; 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 } // namespace utility
} }

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

@ -4,6 +4,17 @@
#include "MicroCore.h" #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 namespace xmreg
{ {
/** /**
@ -46,9 +57,17 @@ namespace xmreg
//db_flags = DEFAULT_FLAGS; //db_flags = DEFAULT_FLAGS;
HardFork* m_hardfork = nullptr;
BlockchainDB* db = 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 try
{ {
// try opening lmdb database files // try opening lmdb database files
@ -69,7 +88,7 @@ namespace xmreg
// initialize Blockchain object to manage // initialize Blockchain object to manage
// the database. // the database.
return m_blockchain_storage.init(db, false); return m_blockchain_storage.init(db, m_hardfork, false);
} }
/** /**

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

@ -15,9 +15,8 @@
#include "storages/http_abstract_invoke.h" #include "storages/http_abstract_invoke.h"
#include "cryptonote_core/cryptonote_basic.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 "cryptonote_core/blockchain.h"
#include "blockchain_db/lmdb/db_lmdb.h" #include "blockchain_db/lmdb/db_lmdb.h"

Loading…
Cancel
Save