it complies and crow updated
This commit is contained in:
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
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "routing.h"
|
#include "routing.h"
|
||||||
#include "middleware_context.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)
|
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,23 +172,23 @@ 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(
|
||||||
// make static_assert dependent to T; always false
|
// 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.");
|
"Define CROW_ENABLE_SSL to enable ssl support.");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
||||||
// make static_assert dependent to T; always false
|
// 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.");
|
"Define CROW_ENABLE_SSL to enable ssl support.");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -40,12 +40,12 @@ namespace crow
|
||||||
response() {}
|
response() {}
|
||||||
explicit response(int code) : code(code) {}
|
explicit response(int code) : code(code) {}
|
||||||
response(std::string body) : body(std::move(body)) {}
|
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(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();
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ namespace crow
|
||||||
if (!completed_)
|
if (!completed_)
|
||||||
{
|
{
|
||||||
completed_ = true;
|
completed_ = true;
|
||||||
|
|
||||||
if (complete_request_handler_)
|
if (complete_request_handler_)
|
||||||
{
|
{
|
||||||
complete_request_handler_();
|
complete_request_handler_();
|
||||||
|
@ -118,7 +118,7 @@ namespace crow
|
||||||
bool completed_{};
|
bool completed_{};
|
||||||
std::function<void()> complete_request_handler_;
|
std::function<void()> complete_request_handler_;
|
||||||
std::function<bool()> is_alive_helper_;
|
std::function<bool()> is_alive_helper_;
|
||||||
|
|
||||||
//In case of a JSON object, set the Content-Type header
|
//In case of a JSON object, set the Content-Type header
|
||||||
void json_mode()
|
void json_mode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,17 +20,18 @@ namespace crow
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
using tcp = asio::ip::tcp;
|
using tcp = asio::ip::tcp;
|
||||||
|
|
||||||
template <typename Handler, typename Adaptor = SocketAdaptor, typename ... Middlewares>
|
template <typename Handler, typename Adaptor = SocketAdaptor, typename ... Middlewares>
|
||||||
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();
|
||||||
|
|
||||||
|
@ -145,7 +151,7 @@ namespace crow
|
||||||
is, handler_, server_name_, middlewares_,
|
is, handler_, server_name_, middlewares_,
|
||||||
get_cached_date_str_pool_[roundrobin_index_], *timer_queue_pool_[roundrobin_index_],
|
get_cached_date_str_pool_[roundrobin_index_], *timer_queue_pool_[roundrobin_index_],
|
||||||
adaptor_ctx_);
|
adaptor_ctx_);
|
||||||
acceptor_.async_accept(p->socket(),
|
acceptor_.async_accept(p->socket(),
|
||||||
[this, p, &is](boost::system::error_code ec)
|
[this, p, &is](boost::system::error_code ec)
|
||||||
{
|
{
|
||||||
if (!ec)
|
if (!ec)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
4
main.cpp
4
main.cpp
|
@ -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,8 +57,16 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -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…
Reference in New Issue