diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bea779..34fa1bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/ext/crow/common.h b/ext/crow/common.h old mode 100644 new mode 100755 index 8808d6a..8203378 --- a/ext/crow/common.h +++ b/ext/crow/common.h @@ -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 diff --git a/ext/crow/crow.h b/ext/crow/crow.h old mode 100644 new mode 100755 index ec4c0ee..00209c7 --- a/ext/crow/crow.h +++ b/ext/crow/crow.h @@ -9,7 +9,7 @@ #include #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 + 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(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(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 - 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::value, + std::is_base_of::value, "Define CROW_ENABLE_SSL to enable ssl support."); return *this; } template - 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::value, + std::is_base_of::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_; + +#ifdef CROW_ENABLE_SSL + std::unique_ptr ssl_server_; +#endif + std::unique_ptr server_; }; template using App = Crow; using SimpleApp = Crow<>; -}; - +} diff --git a/ext/crow/http_connection.h b/ext/crow/http_connection.h old mode 100644 new mode 100755 index 69b87b0..5517521 --- a/ext/crow/http_connection.h +++ b/ext/crow/http_connection.h @@ -98,28 +98,28 @@ namespace crow template typename std::enable_if::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(), ctx); } template typename std::enable_if::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()); } template typename std::enable_if::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(), ctx); } template typename std::enable_if::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()); } @@ -146,14 +146,14 @@ namespace crow } template - 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 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(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << parser_.http_major << "." << parser_.http_minor << ' ' @@ -296,6 +311,7 @@ namespace crow ctx_ = detail::context(); 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(); diff --git a/ext/crow/http_parser_merged.h b/ext/crow/http_parser_merged.h old mode 100644 new mode 100755 index e058517..2a10252 --- a/ext/crow/http_parser_merged.h +++ b/ext/crow/http_parser_merged.h @@ -19,16 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ -#ifndef http_parser_h -#define http_parser_h +#ifndef CROW_http_parser_h +#define CROW_http_parser_h #ifdef __cplusplus extern "C" { #endif /* Also update SONAME in the Makefile whenever you change these. */ -#define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 3 -#define HTTP_PARSER_VERSION_PATCH 0 +#define CROW_HTTP_PARSER_VERSION_MAJOR 2 +#define CROW_HTTP_PARSER_VERSION_MINOR 3 +#define CROW_HTTP_PARSER_VERSION_PATCH 0 #include #if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600) @@ -49,8 +49,8 @@ typedef unsigned __int64 uint64_t; /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run * faster */ -#ifndef HTTP_PARSER_STRICT -# define HTTP_PARSER_STRICT 1 +#ifndef CROW_HTTP_PARSER_STRICT +# define CROW_HTTP_PARSER_STRICT 1 #endif /* Maximium header size allowed. If the macro is not defined @@ -60,8 +60,8 @@ typedef unsigned __int64 uint64_t; * the effective limit on the size of the header, define the macro * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) */ -#ifndef HTTP_MAX_HEADER_SIZE -# define HTTP_MAX_HEADER_SIZE (80*1024) +#ifndef CROW_HTTP_MAX_HEADER_SIZE +# define CROW_HTTP_MAX_HEADER_SIZE (80*1024) #endif typedef struct http_parser http_parser; @@ -86,46 +86,46 @@ typedef int (*http_cb) (http_parser*); /* Request Methods */ -#define HTTP_METHOD_MAP(XX) \ - XX(0, DELETE, DELETE) \ - XX(1, GET, GET) \ - XX(2, HEAD, HEAD) \ - XX(3, POST, POST) \ - XX(4, PUT, PUT) \ +#define CROW_HTTP_METHOD_MAP(CROW_XX) \ + CROW_XX(0, DELETE, DELETE) \ + CROW_XX(1, GET, GET) \ + CROW_XX(2, HEAD, HEAD) \ + CROW_XX(3, POST, POST) \ + CROW_XX(4, PUT, PUT) \ /* pathological */ \ - XX(5, CONNECT, CONNECT) \ - XX(6, OPTIONS, OPTIONS) \ - XX(7, TRACE, TRACE) \ + CROW_XX(5, CONNECT, CONNECT) \ + CROW_XX(6, OPTIONS, OPTIONS) \ + CROW_XX(7, TRACE, TRACE) \ /* webdav */ \ - XX(8, COPY, COPY) \ - XX(9, LOCK, LOCK) \ - XX(10, MKCOL, MKCOL) \ - XX(11, MOVE, MOVE) \ - XX(12, PROPFIND, PROPFIND) \ - XX(13, PROPPATCH, PROPPATCH) \ - XX(14, SEARCH, SEARCH) \ - XX(15, UNLOCK, UNLOCK) \ + CROW_XX(8, COPY, COPY) \ + CROW_XX(9, LOCK, LOCK) \ + CROW_XX(10, MKCOL, MKCOL) \ + CROW_XX(11, MOVE, MOVE) \ + CROW_XX(12, PROPFIND, PROPFIND) \ + CROW_XX(13, PROPPATCH, PROPPATCH) \ + CROW_XX(14, SEARCH, SEARCH) \ + CROW_XX(15, UNLOCK, UNLOCK) \ /* subversion */ \ - XX(16, REPORT, REPORT) \ - XX(17, MKACTIVITY, MKACTIVITY) \ - XX(18, CHECKOUT, CHECKOUT) \ - XX(19, MERGE, MERGE) \ + CROW_XX(16, REPORT, REPORT) \ + CROW_XX(17, MKACTIVITY, MKACTIVITY) \ + CROW_XX(18, CHECKOUT, CHECKOUT) \ + CROW_XX(19, MERGE, MERGE) \ /* upnp */ \ - XX(20, MSEARCH, M-SEARCH) \ - XX(21, NOTIFY, NOTIFY) \ - XX(22, SUBSCRIBE, SUBSCRIBE) \ - XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \ + CROW_XX(20, MSEARCH, M-SEARCH) \ + CROW_XX(21, NOTIFY, NOTIFY) \ + CROW_XX(22, SUBSCRIBE, SUBSCRIBE) \ + CROW_XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \ /* RFC-5789 */ \ - XX(24, PATCH, PATCH) \ - XX(25, PURGE, PURGE) \ + CROW_XX(24, PATCH, PATCH) \ + CROW_XX(25, PURGE, PURGE) \ /* CalDAV */ \ - XX(26, MKCALENDAR, MKCALENDAR) \ + CROW_XX(26, MKCALENDAR, MKCALENDAR) \ enum http_method { -#define XX(num, name, string) HTTP_##name = num, - HTTP_METHOD_MAP(XX) -#undef XX +#define CROW_XX(num, name, string) HTTP_##name = num, + CROW_HTTP_METHOD_MAP(CROW_XX) +#undef CROW_XX }; @@ -147,58 +147,58 @@ enum flags * * The provided argument should be a macro that takes 2 arguments. */ -#define HTTP_ERRNO_MAP(XX) \ +#define CROW_HTTP_ERRNO_MAP(CROW_XX) \ /* No error */ \ - XX(OK, "success") \ + CROW_XX(OK, "success") \ \ /* Callback-related errors */ \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - XX(CB_message_complete, "the on_message_complete callback failed") \ - XX(CB_status, "the on_status callback failed") \ + CROW_XX(CB_message_begin, "the on_message_begin callback failed") \ + CROW_XX(CB_url, "the on_url callback failed") \ + CROW_XX(CB_header_field, "the on_header_field callback failed") \ + CROW_XX(CB_header_value, "the on_header_value callback failed") \ + CROW_XX(CB_headers_complete, "the on_headers_complete callback failed") \ + CROW_XX(CB_body, "the on_body callback failed") \ + CROW_XX(CB_message_complete, "the on_message_complete callback failed") \ + CROW_XX(CB_status, "the on_status callback failed") \ \ /* Parsing-related errors */ \ - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ - XX(HEADER_OVERFLOW, \ + CROW_XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ + CROW_XX(HEADER_OVERFLOW, \ "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ + CROW_XX(CLOSED_CONNECTION, \ "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - XX(INVALID_STATUS, "invalid HTTP status code") \ - XX(INVALID_METHOD, "invalid HTTP method") \ - XX(INVALID_URL, "invalid URL") \ - XX(INVALID_HOST, "invalid host") \ - XX(INVALID_PORT, "invalid port") \ - XX(INVALID_PATH, "invalid path") \ - XX(INVALID_QUERY_STRING, "invalid query string") \ - XX(INVALID_FRAGMENT, "invalid fragment") \ - XX(LF_EXPECTED, "LF character expected") \ - XX(INVALID_HEADER_TOKEN, "invalid character in header") \ - XX(INVALID_CONTENT_LENGTH, \ + CROW_XX(INVALID_VERSION, "invalid HTTP version") \ + CROW_XX(INVALID_STATUS, "invalid HTTP status code") \ + CROW_XX(INVALID_METHOD, "invalid HTTP method") \ + CROW_XX(INVALID_URL, "invalid URL") \ + CROW_XX(INVALID_HOST, "invalid host") \ + CROW_XX(INVALID_PORT, "invalid port") \ + CROW_XX(INVALID_PATH, "invalid path") \ + CROW_XX(INVALID_QUERY_STRING, "invalid query string") \ + CROW_XX(INVALID_FRAGMENT, "invalid fragment") \ + CROW_XX(LF_EXPECTED, "CROW_LF character expected") \ + CROW_XX(INVALID_HEADER_TOKEN, "invalid character in header") \ + CROW_XX(INVALID_CONTENT_LENGTH, \ "invalid character in content-length header") \ - XX(INVALID_CHUNK_SIZE, \ + CROW_XX(INVALID_CHUNK_SIZE, \ "invalid character in chunk size header") \ - XX(INVALID_CONSTANT, "invalid constant string") \ - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ - XX(STRICT, "strict mode assertion failed") \ - XX(PAUSED, "parser is paused") \ - XX(UNKNOWN, "an unknown error occurred") + CROW_XX(INVALID_CONSTANT, "invalid constant string") \ + CROW_XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ + CROW_XX(STRICT, "strict mode assertion failed") \ + CROW_XX(PAUSED, "parser is paused") \ + CROW_XX(UNKNOWN, "an unknown error occurred") /* Define HPE_* values for each errno value above */ -#define HTTP_ERRNO_GEN(n, s) HPE_##n, +#define CROW_HTTP_ERRNO_GEN(n, s) HPE_##n, enum http_errno { - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) + CROW_HTTP_ERRNO_MAP(CROW_HTTP_ERRNO_GEN) }; -#undef HTTP_ERRNO_GEN +#undef CROW_HTTP_ERRNO_GEN /* Get an http_errno value from an http_parser */ -#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) +#define CROW_HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) struct http_parser { @@ -353,70 +353,70 @@ int http_body_is_final(const http_parser *parser); #include #include -#ifndef ULLONG_MAX -# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ +#ifndef CROW_ULLONG_MAX +# define CROW_ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ #endif -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#ifndef CROW_MIN +# define CROW_MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#ifndef CROW_ARRAY_SIZE +# define CROW_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif -#ifndef BIT_AT -# define BIT_AT(a, i) \ +#ifndef CROW_BIT_AT +# define CROW_BIT_AT(a, i) \ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ (1 << ((unsigned int) (i) & 7)))) #endif -#ifndef ELEM_AT -# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) +#ifndef CROW_ELEM_AT +# define CROW_ELEM_AT(a, i, v) ((unsigned int) (i) < CROW_ARRAY_SIZE(a) ? (a)[(i)] : (v)) #endif -#define SET_ERRNO(e) \ +#define CROW_SET_ERRNO(e) \ do { \ parser->http_errno = (e); \ } while(0) /* Run the notify callback FOR, returning ER if it fails */ -#define CALLBACK_NOTIFY_(FOR, ER) \ +#define CROW_CALLBACK_NOTIFY_(FOR, ER) \ do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + assert(CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (settings->on_##FOR) { \ if (0 != settings->on_##FOR(parser)) { \ - SET_ERRNO(HPE_CB_##FOR); \ + CROW_SET_ERRNO(HPE_CB_##FOR); \ } \ \ /* We either errored above or got paused; get out */ \ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ + if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ } while (0) /* Run the notify callback FOR and consume the current byte */ -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) +#define CROW_CALLBACK_NOTIFY(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data + 1) /* Run the notify callback FOR and don't consume the current byte */ -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) +#define CROW_CALLBACK_NOTIFY_NOADVANCE(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data) /* Run data callback FOR with LEN bytes, returning ER if it fails */ -#define CALLBACK_DATA_(FOR, LEN, ER) \ +#define CROW_CALLBACK_DATA_(FOR, LEN, ER) \ do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + assert(CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (FOR##_mark) { \ if (settings->on_##FOR) { \ if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \ - SET_ERRNO(HPE_CB_##FOR); \ + CROW_SET_ERRNO(HPE_CB_##FOR); \ } \ \ /* We either errored above or got paused; get out */ \ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ + if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ @@ -425,15 +425,15 @@ do { \ } while (0) /* Run the data callback FOR and consume the current byte */ -#define CALLBACK_DATA(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) +#define CROW_CALLBACK_DATA(FOR) \ + CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) /* Run the data callback FOR and don't consume the current byte */ -#define CALLBACK_DATA_NOADVANCE(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) +#define CROW_CALLBACK_DATA_NOADVANCE(FOR) \ + CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) /* Set the mark FOR; non-destructive if mark is already set */ -#define MARK(FOR) \ +#define CROW_MARK(FOR) \ do { \ if (!FOR##_mark) { \ FOR##_mark = p; \ @@ -441,14 +441,14 @@ do { \ } while (0) -#define PROXY_CONNECTION "proxy-connection" -#define CONNECTION "connection" -#define CONTENT_LENGTH "content-length" -#define TRANSFER_ENCODING "transfer-encoding" -#define UPGRADE "upgrade" -#define CHUNKED "chunked" -#define KEEP_ALIVE "keep-alive" -#define CLOSE "close" +#define CROW_PROXY_CONNECTION "proxy-connection" +#define CROW_CONNECTION "connection" +#define CROW_CONTENT_LENGTH "content-length" +#define CROW_TRANSFER_ENCODING "transfer-encoding" +#define CROW_UPGRADE "upgrade" +#define CROW_CHUNKED "chunked" +#define CROW_KEEP_ALIVE "keep-alive" +#define CROW_CLOSE "close" @@ -520,7 +520,7 @@ enum state /* Important: 's_headers_done' must be the last 'header' state. All * states beyond this must be 'body' states. It is used for overflow - * checking. See the PARSING_HEADER() macro. + * checking. See the CROW_PARSING_HEADER() macro. */ , s_chunk_data @@ -534,7 +534,7 @@ enum state }; -#define PARSING_HEADER(state) (state <= s_headers_done) +#define CROW_PARSING_HEADER(state) (state <= s_headers_done) enum header_states @@ -578,48 +578,48 @@ enum http_host_state }; /* Macros for character classes; depends on strict-mode */ -#define CR '\r' -#define LF '\n' -#define LOWER(c) (unsigned char)(c | 0x20) -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') -#define IS_NUM(c) ((c) >= '0' && (c) <= '9') -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ +#define CROW_CR '\r' +#define CROW_LF '\n' +#define CROW_LOWER(c) (unsigned char)(c | 0x20) +#define CROW_IS_ALPHA(c) (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'z') +#define CROW_IS_NUM(c) ((c) >= '0' && (c) <= '9') +#define CROW_IS_ALPHANUM(c) (CROW_IS_ALPHA(c) || CROW_IS_NUM(c)) +#define CROW_IS_HEX(c) (CROW_IS_NUM(c) || (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'f')) +#define CROW_IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ (c) == ')') -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ +#define CROW_IS_USERINFO_CHAR(c) (CROW_IS_ALPHANUM(c) || CROW_IS_MARK(c) || (c) == '%' || \ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') -#if HTTP_PARSER_STRICT -#define TOKEN(c) (tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') +#if CROW_HTTP_PARSER_STRICT +#define CROW_TOKEN(c) (tokens[(unsigned char)c]) +#define CROW_IS_URL_CHAR(c) (CROW_BIT_AT(normal_url_char, (unsigned char)c)) +#define CROW_IS_HOST_CHAR(c) (CROW_IS_ALPHANUM(c) || (c) == '.' || (c) == '-') #else -#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) \ - (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) -#define IS_HOST_CHAR(c) \ - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') +#define CROW_TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) +#define CROW_IS_URL_CHAR(c) \ + (CROW_BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) +#define CROW_IS_HOST_CHAR(c) \ + (CROW_IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') #endif -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) +#define CROW_start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) -#if HTTP_PARSER_STRICT -# define STRICT_CHECK(cond) \ +#if CROW_HTTP_PARSER_STRICT +# define CROW_STRICT_CHECK(cond) \ do { \ if (cond) { \ - SET_ERRNO(HPE_STRICT); \ + CROW_SET_ERRNO(HPE_STRICT); \ goto error; \ } \ } while (0) -# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) +# define CROW_NEW_MESSAGE() (http_should_keep_alive(parser) ? CROW_start_state : s_dead) #else -# define STRICT_CHECK(cond) -# define NEW_MESSAGE() start_state +# define CROW_STRICT_CHECK(cond) +# define CROW_NEW_MESSAGE() CROW_start_state #endif @@ -640,10 +640,10 @@ int http_message_needs_eof(const http_parser *parser); inline enum state parse_url_char(enum state s, const char ch) { -#if HTTP_PARSER_STRICT -# define T(v) 0 +#if CROW_HTTP_PARSER_STRICT +# define CROW_T(v) 0 #else -# define T(v) v +# define CROW_T(v) v #endif @@ -651,7 +651,7 @@ static const uint8_t normal_url_char[32] = { /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, + 0 | CROW_T(2) | 0 | 0 | CROW_T(16) | 0 | 0 | 0, /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ @@ -668,7 +668,7 @@ static const uint8_t normal_url_char[32] = { 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ +/* 80 P 81 Q 82 R 83 S 84 CROW_T 85 U 86 V 87 W */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, @@ -681,13 +681,13 @@ static const uint8_t normal_url_char[32] = { /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; -#undef T +#undef CROW_T if (ch == ' ' || ch == '\r' || ch == '\n') { return s_dead; } -#if HTTP_PARSER_STRICT +#if CROW_HTTP_PARSER_STRICT if (ch == '\t' || ch == '\f') { return s_dead; } @@ -703,14 +703,14 @@ static const uint8_t normal_url_char[32] = { return s_req_path; } - if (IS_ALPHA(ch)) { + if (CROW_IS_ALPHA(ch)) { return s_req_schema; } break; case s_req_schema: - if (IS_ALPHA(ch)) { + if (CROW_IS_ALPHA(ch)) { return s; } @@ -754,14 +754,14 @@ static const uint8_t normal_url_char[32] = { return s_req_server_with_at; } - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { + if (CROW_IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { return s_req_server; } break; case s_req_path: - if (IS_URL_CHAR(ch)) { + if (CROW_IS_URL_CHAR(ch)) { return s; } @@ -777,7 +777,7 @@ static const uint8_t normal_url_char[32] = { case s_req_query_string_start: case s_req_query_string: - if (IS_URL_CHAR(ch)) { + if (CROW_IS_URL_CHAR(ch)) { return s_req_query_string; } @@ -793,7 +793,7 @@ static const uint8_t normal_url_char[32] = { break; case s_req_fragment_start: - if (IS_URL_CHAR(ch)) { + if (CROW_IS_URL_CHAR(ch)) { return s_req_fragment; } @@ -808,7 +808,7 @@ static const uint8_t normal_url_char[32] = { break; case s_req_fragment: - if (IS_URL_CHAR(ch)) { + if (CROW_IS_URL_CHAR(ch)) { return s; } @@ -835,9 +835,9 @@ inline size_t http_parser_execute (http_parser *parser, { static const char *method_strings[] = { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX +#define CROW_XX(num, name, string) #string, + CROW_HTTP_METHOD_MAP(CROW_XX) +#undef CROW_XX }; /* Tokens as defined by rfc 2616. Also lowercases them. @@ -905,17 +905,17 @@ static const int8_t unhex[256] = const char *status_mark = 0; /* We're in an error state. Don't bother doing anything. */ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { return 0; } if (len == 0) { switch (parser->state) { case s_body_identity_eof: - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if + /* Use of CROW_CALLBACK_NOTIFY() here would erroneously return 1 byte read if * we got paused. */ - CALLBACK_NOTIFY_NOADVANCE(message_complete); + CROW_CALLBACK_NOTIFY_NOADVANCE(message_complete); return 0; case s_dead: @@ -925,7 +925,7 @@ static const int8_t unhex[256] = return 0; default: - SET_ERRNO(HPE_INVALID_EOF_STATE); + CROW_SET_ERRNO(HPE_INVALID_EOF_STATE); return 1; } } @@ -957,21 +957,21 @@ static const int8_t unhex[256] = for (p=data; p != data + len; p++) { ch = *p; - if (PARSING_HEADER(parser->state)) { + if (CROW_PARSING_HEADER(parser->state)) { ++parser->nread; /* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * line) to exceed CROW_HTTP_MAX_HEADER_SIZE. This check is here to protect * embedders against denial-of-service attacks where the attacker feeds * us a never-ending header that the embedder keeps buffering. * * This check is arguably the responsibility of embedders but we're doing * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * make the web a little safer. CROW_HTTP_MAX_HEADER_SIZE is still far bigger * than any reasonable request or response so this should never affect * day-to-day operation. */ - if (parser->nread > (HTTP_MAX_HEADER_SIZE)) { - SET_ERRNO(HPE_HEADER_OVERFLOW); + if (parser->nread > (CROW_HTTP_MAX_HEADER_SIZE)) { + CROW_SET_ERRNO(HPE_HEADER_OVERFLOW); goto error; } } @@ -983,23 +983,23 @@ static const int8_t unhex[256] = /* this state is used after a 'Connection: close' message * the parser will error out if it reads another message */ - if (ch == CR || ch == LF) + if (ch == CROW_CR || ch == CROW_LF) break; - SET_ERRNO(HPE_CLOSED_CONNECTION); + CROW_SET_ERRNO(HPE_CLOSED_CONNECTION); goto error; case s_start_req_or_res: { - if (ch == CR || ch == LF) + if (ch == CROW_CR || ch == CROW_LF) break; parser->flags = 0; - parser->content_length = ULLONG_MAX; + parser->content_length = CROW_ULLONG_MAX; if (ch == 'H') { parser->state = s_res_or_resp_H; - CALLBACK_NOTIFY(message_begin); + CROW_CALLBACK_NOTIFY(message_begin); } else { parser->type = HTTP_REQUEST; parser->state = s_start_req; @@ -1015,7 +1015,7 @@ static const int8_t unhex[256] = parser->state = s_res_HT; } else { if (ch != 'E') { - SET_ERRNO(HPE_INVALID_CONSTANT); + CROW_SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } @@ -1029,49 +1029,49 @@ static const int8_t unhex[256] = case s_start_res: { parser->flags = 0; - parser->content_length = ULLONG_MAX; + parser->content_length = CROW_ULLONG_MAX; switch (ch) { case 'H': parser->state = s_res_H; break; - case CR: - case LF: + case CROW_CR: + case CROW_LF: break; default: - SET_ERRNO(HPE_INVALID_CONSTANT); + CROW_SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } - CALLBACK_NOTIFY(message_begin); + CROW_CALLBACK_NOTIFY(message_begin); break; } case s_res_H: - STRICT_CHECK(ch != 'T'); + CROW_STRICT_CHECK(ch != 'T'); parser->state = s_res_HT; break; case s_res_HT: - STRICT_CHECK(ch != 'T'); + CROW_STRICT_CHECK(ch != 'T'); parser->state = s_res_HTT; break; case s_res_HTT: - STRICT_CHECK(ch != 'P'); + CROW_STRICT_CHECK(ch != 'P'); parser->state = s_res_HTTP; break; case s_res_HTTP: - STRICT_CHECK(ch != '/'); + CROW_STRICT_CHECK(ch != '/'); parser->state = s_res_first_http_major; break; case s_res_first_http_major: if (ch < '0' || ch > '9') { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1087,8 +1087,8 @@ static const int8_t unhex[256] = break; } - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1096,7 +1096,7 @@ static const int8_t unhex[256] = parser->http_major += ch - '0'; if (parser->http_major > 999) { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1105,8 +1105,8 @@ static const int8_t unhex[256] = /* first digit of minor HTTP version */ case s_res_first_http_minor: - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1122,8 +1122,8 @@ static const int8_t unhex[256] = break; } - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1131,7 +1131,7 @@ static const int8_t unhex[256] = parser->http_minor += ch - '0'; if (parser->http_minor > 999) { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1140,12 +1140,12 @@ static const int8_t unhex[256] = case s_res_first_status_code: { - if (!IS_NUM(ch)) { + if (!CROW_IS_NUM(ch)) { if (ch == ' ') { break; } - SET_ERRNO(HPE_INVALID_STATUS); + CROW_SET_ERRNO(HPE_INVALID_STATUS); goto error; } parser->status_code = ch - '0'; @@ -1155,19 +1155,19 @@ static const int8_t unhex[256] = case s_res_status_code: { - if (!IS_NUM(ch)) { + if (!CROW_IS_NUM(ch)) { switch (ch) { case ' ': parser->state = s_res_status_start; break; - case CR: + case CROW_CR: parser->state = s_res_line_almost_done; break; - case LF: + case CROW_LF: parser->state = s_header_field_start; break; default: - SET_ERRNO(HPE_INVALID_STATUS); + CROW_SET_ERRNO(HPE_INVALID_STATUS); goto error; } break; @@ -1177,7 +1177,7 @@ static const int8_t unhex[256] = parser->status_code += ch - '0'; if (parser->status_code > 999) { - SET_ERRNO(HPE_INVALID_STATUS); + CROW_SET_ERRNO(HPE_INVALID_STATUS); goto error; } @@ -1186,51 +1186,51 @@ static const int8_t unhex[256] = case s_res_status_start: { - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_res_line_almost_done; break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_field_start; break; } - MARK(status); + CROW_MARK(status); parser->state = s_res_status; parser->index = 0; break; } case s_res_status: - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_res_line_almost_done; - CALLBACK_DATA(status); + CROW_CALLBACK_DATA(status); break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_field_start; - CALLBACK_DATA(status); + CROW_CALLBACK_DATA(status); break; } break; case s_res_line_almost_done: - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->state = s_header_field_start; break; case s_start_req: { - if (ch == CR || ch == LF) + if (ch == CROW_CR || ch == CROW_LF) break; parser->flags = 0; - parser->content_length = ULLONG_MAX; + parser->content_length = CROW_ULLONG_MAX; - if (!IS_ALPHA(ch)) { - SET_ERRNO(HPE_INVALID_METHOD); + if (!CROW_IS_ALPHA(ch)) { + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } @@ -1253,12 +1253,12 @@ static const int8_t unhex[256] = case 'T': parser->method = HTTP_TRACE; break; case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break; default: - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } parser->state = s_req_method; - CALLBACK_NOTIFY(message_begin); + CROW_CALLBACK_NOTIFY(message_begin); break; } @@ -1267,7 +1267,7 @@ static const int8_t unhex[256] = { const char *matcher; if (ch == '\0') { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } @@ -1282,7 +1282,7 @@ static const int8_t unhex[256] = } else if (parser->index == 2 && ch == 'P') { parser->method = HTTP_COPY; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->method == HTTP_MKCOL) { @@ -1297,14 +1297,14 @@ static const int8_t unhex[256] = } else if (parser->index == 3 && ch == 'A') { parser->method = HTTP_MKCALENDAR; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->method == HTTP_SUBSCRIBE) { if (parser->index == 1 && ch == 'E') { parser->method = HTTP_SEARCH; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->index == 1 && parser->method == HTTP_POST) { @@ -1315,7 +1315,7 @@ static const int8_t unhex[256] = } else if (ch == 'A') { parser->method = HTTP_PATCH; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->index == 2) { @@ -1323,24 +1323,24 @@ static const int8_t unhex[256] = if (ch == 'R') { parser->method = HTTP_PURGE; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->method == HTTP_UNLOCK) { if (ch == 'S') { parser->method = HTTP_UNSUBSCRIBE; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { parser->method = HTTP_PROPPATCH; } else { - SET_ERRNO(HPE_INVALID_METHOD); + CROW_SET_ERRNO(HPE_INVALID_METHOD); goto error; } @@ -1352,14 +1352,14 @@ static const int8_t unhex[256] = { if (ch == ' ') break; - MARK(url); + CROW_MARK(url); if (parser->method == HTTP_CONNECT) { parser->state = s_req_server_start; } parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { - SET_ERRNO(HPE_INVALID_URL); + CROW_SET_ERRNO(HPE_INVALID_URL); goto error; } @@ -1374,14 +1374,14 @@ static const int8_t unhex[256] = switch (ch) { /* No whitespace allowed here */ case ' ': - case CR: - case LF: - SET_ERRNO(HPE_INVALID_URL); + case CROW_CR: + case CROW_LF: + CROW_SET_ERRNO(HPE_INVALID_URL); goto error; default: parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { - SET_ERRNO(HPE_INVALID_URL); + CROW_SET_ERRNO(HPE_INVALID_URL); goto error; } } @@ -1400,21 +1400,21 @@ static const int8_t unhex[256] = switch (ch) { case ' ': parser->state = s_req_http_start; - CALLBACK_DATA(url); + CROW_CALLBACK_DATA(url); break; - case CR: - case LF: + case CROW_CR: + case CROW_LF: parser->http_major = 0; parser->http_minor = 9; - parser->state = (ch == CR) ? + parser->state = (ch == CROW_CR) ? s_req_line_almost_done : s_header_field_start; - CALLBACK_DATA(url); + CROW_CALLBACK_DATA(url); break; default: parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { - SET_ERRNO(HPE_INVALID_URL); + CROW_SET_ERRNO(HPE_INVALID_URL); goto error; } } @@ -1429,35 +1429,35 @@ static const int8_t unhex[256] = case ' ': break; default: - SET_ERRNO(HPE_INVALID_CONSTANT); + CROW_SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } break; case s_req_http_H: - STRICT_CHECK(ch != 'T'); + CROW_STRICT_CHECK(ch != 'T'); parser->state = s_req_http_HT; break; case s_req_http_HT: - STRICT_CHECK(ch != 'T'); + CROW_STRICT_CHECK(ch != 'T'); parser->state = s_req_http_HTT; break; case s_req_http_HTT: - STRICT_CHECK(ch != 'P'); + CROW_STRICT_CHECK(ch != 'P'); parser->state = s_req_http_HTTP; break; case s_req_http_HTTP: - STRICT_CHECK(ch != '/'); + CROW_STRICT_CHECK(ch != '/'); parser->state = s_req_first_http_major; break; /* first digit of major HTTP version */ case s_req_first_http_major: if (ch < '1' || ch > '9') { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1473,8 +1473,8 @@ static const int8_t unhex[256] = break; } - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1482,7 +1482,7 @@ static const int8_t unhex[256] = parser->http_major += ch - '0'; if (parser->http_major > 999) { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1491,8 +1491,8 @@ static const int8_t unhex[256] = /* first digit of minor HTTP version */ case s_req_first_http_minor: - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1503,20 +1503,20 @@ static const int8_t unhex[256] = /* minor HTTP version or end of request line */ case s_req_http_minor: { - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_req_line_almost_done; break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_field_start; break; } /* XXX allow spaces after digit? */ - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1524,7 +1524,7 @@ static const int8_t unhex[256] = parser->http_minor += ch - '0'; if (parser->http_minor > 999) { - SET_ERRNO(HPE_INVALID_VERSION); + CROW_SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1534,8 +1534,8 @@ static const int8_t unhex[256] = /* end of request line */ case s_req_line_almost_done: { - if (ch != LF) { - SET_ERRNO(HPE_LF_EXPECTED); + if (ch != CROW_LF) { + CROW_SET_ERRNO(HPE_LF_EXPECTED); goto error; } @@ -1545,26 +1545,26 @@ static const int8_t unhex[256] = case s_header_field_start: { - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_headers_almost_done; break; } - if (ch == LF) { + if (ch == CROW_LF) { /* they might be just sending \n instead of \r\n so this would be * the second \n to denote the end of headers*/ parser->state = s_headers_almost_done; goto reexecute_byte; } - c = TOKEN(ch); + c = CROW_TOKEN(ch); if (!c) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + CROW_SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } - MARK(header_field); + CROW_MARK(header_field); parser->index = 0; parser->state = s_header_field; @@ -1595,7 +1595,7 @@ static const int8_t unhex[256] = case s_header_field: { - c = TOKEN(ch); + c = CROW_TOKEN(ch); if (c) { switch (parser->header_state) { @@ -1631,10 +1631,10 @@ static const int8_t unhex[256] = case h_matching_connection: parser->index++; - if (parser->index > sizeof(CONNECTION)-1 - || c != CONNECTION[parser->index]) { + if (parser->index > sizeof(CROW_CONNECTION)-1 + || c != CROW_CONNECTION[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(CONNECTION)-2) { + } else if (parser->index == sizeof(CROW_CONNECTION)-2) { parser->header_state = h_connection; } break; @@ -1643,10 +1643,10 @@ static const int8_t unhex[256] = case h_matching_proxy_connection: parser->index++; - if (parser->index > sizeof(PROXY_CONNECTION)-1 - || c != PROXY_CONNECTION[parser->index]) { + if (parser->index > sizeof(CROW_PROXY_CONNECTION)-1 + || c != CROW_PROXY_CONNECTION[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { + } else if (parser->index == sizeof(CROW_PROXY_CONNECTION)-2) { parser->header_state = h_connection; } break; @@ -1655,10 +1655,10 @@ static const int8_t unhex[256] = case h_matching_content_length: parser->index++; - if (parser->index > sizeof(CONTENT_LENGTH)-1 - || c != CONTENT_LENGTH[parser->index]) { + if (parser->index > sizeof(CROW_CONTENT_LENGTH)-1 + || c != CROW_CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + } else if (parser->index == sizeof(CROW_CONTENT_LENGTH)-2) { parser->header_state = h_content_length; } break; @@ -1667,10 +1667,10 @@ static const int8_t unhex[256] = case h_matching_transfer_encoding: parser->index++; - if (parser->index > sizeof(TRANSFER_ENCODING)-1 - || c != TRANSFER_ENCODING[parser->index]) { + if (parser->index > sizeof(CROW_TRANSFER_ENCODING)-1 + || c != CROW_TRANSFER_ENCODING[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { + } else if (parser->index == sizeof(CROW_TRANSFER_ENCODING)-2) { parser->header_state = h_transfer_encoding; } break; @@ -1679,10 +1679,10 @@ static const int8_t unhex[256] = case h_matching_upgrade: parser->index++; - if (parser->index > sizeof(UPGRADE)-1 - || c != UPGRADE[parser->index]) { + if (parser->index > sizeof(CROW_UPGRADE)-1 + || c != CROW_UPGRADE[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(UPGRADE)-2) { + } else if (parser->index == sizeof(CROW_UPGRADE)-2) { parser->header_state = h_upgrade; } break; @@ -1703,35 +1703,35 @@ static const int8_t unhex[256] = if (ch == ':') { parser->state = s_header_value_discard_ws; - CALLBACK_DATA(header_field); + CROW_CALLBACK_DATA(header_field); break; } - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_header_almost_done; - CALLBACK_DATA(header_field); + CROW_CALLBACK_DATA(header_field); break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_field_start; - CALLBACK_DATA(header_field); + CROW_CALLBACK_DATA(header_field); break; } - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + CROW_SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } case s_header_value_discard_ws: if (ch == ' ' || ch == '\t') break; - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_header_value_discard_ws_almost_done; break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_value_discard_lws; break; } @@ -1740,12 +1740,12 @@ static const int8_t unhex[256] = case s_header_value_start: { - MARK(header_value); + CROW_MARK(header_value); parser->state = s_header_value; parser->index = 0; - c = LOWER(ch); + c = CROW_LOWER(ch); switch (parser->header_state) { case h_upgrade: @@ -1763,8 +1763,8 @@ static const int8_t unhex[256] = break; case h_content_length: - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1793,19 +1793,19 @@ static const int8_t unhex[256] = case s_header_value: { - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_header_almost_done; - CALLBACK_DATA(header_value); + CROW_CALLBACK_DATA(header_value); break; } - if (ch == LF) { + if (ch == CROW_LF) { parser->state = s_header_almost_done; - CALLBACK_DATA_NOADVANCE(header_value); + CROW_CALLBACK_DATA_NOADVANCE(header_value); goto reexecute_byte; } - c = LOWER(ch); + c = CROW_LOWER(ch); switch (parser->header_state) { case h_general: @@ -1822,8 +1822,8 @@ static const int8_t unhex[256] = if (ch == ' ') break; - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + if (!CROW_IS_NUM(ch)) { + CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1832,8 +1832,8 @@ static const int8_t unhex[256] = t += ch - '0'; /* Overflow? Test against a conservative limit for simplicity. */ - if ((ULLONG_MAX - 10) / 10 < parser->content_length) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + if ((CROW_ULLONG_MAX - 10) / 10 < parser->content_length) { + CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1844,10 +1844,10 @@ static const int8_t unhex[256] = /* Transfer-Encoding: chunked */ case h_matching_transfer_encoding_chunked: parser->index++; - if (parser->index > sizeof(CHUNKED)-1 - || c != CHUNKED[parser->index]) { + if (parser->index > sizeof(CROW_CHUNKED)-1 + || c != CROW_CHUNKED[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(CHUNKED)-2) { + } else if (parser->index == sizeof(CROW_CHUNKED)-2) { parser->header_state = h_transfer_encoding_chunked; } break; @@ -1855,10 +1855,10 @@ static const int8_t unhex[256] = /* looking for 'Connection: keep-alive' */ case h_matching_connection_keep_alive: parser->index++; - if (parser->index > sizeof(KEEP_ALIVE)-1 - || c != KEEP_ALIVE[parser->index]) { + if (parser->index > sizeof(CROW_KEEP_ALIVE)-1 + || c != CROW_KEEP_ALIVE[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + } else if (parser->index == sizeof(CROW_KEEP_ALIVE)-2) { parser->header_state = h_connection_keep_alive; } break; @@ -1866,9 +1866,9 @@ static const int8_t unhex[256] = /* looking for 'Connection: close' */ case h_matching_connection_close: parser->index++; - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { + if (parser->index > sizeof(CROW_CLOSE)-1 || c != CROW_CLOSE[parser->index]) { parser->header_state = h_general; - } else if (parser->index == sizeof(CLOSE)-2) { + } else if (parser->index == sizeof(CROW_CLOSE)-2) { parser->header_state = h_connection_close; } break; @@ -1889,7 +1889,7 @@ static const int8_t unhex[256] = case s_header_almost_done: { - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->state = s_header_value_lws; break; @@ -1923,7 +1923,7 @@ static const int8_t unhex[256] = case s_header_value_discard_ws_almost_done: { - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->state = s_header_value_discard_lws; break; } @@ -1935,21 +1935,21 @@ static const int8_t unhex[256] = break; } else { /* header value was empty */ - MARK(header_value); + CROW_MARK(header_value); parser->state = s_header_field_start; - CALLBACK_DATA_NOADVANCE(header_value); + CROW_CALLBACK_DATA_NOADVANCE(header_value); goto reexecute_byte; } } case s_headers_almost_done: { - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); if (parser->flags & F_TRAILING) { /* End of a chunked request */ - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); break; } @@ -1965,7 +1965,7 @@ static const int8_t unhex[256] = * is needed for the annoying case of recieving a response to a HEAD * request. * - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so + * We'd like to use CROW_CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so * we have to simulate it by handling a change in errno below. */ if (settings->on_headers_complete) { @@ -1978,12 +1978,12 @@ static const int8_t unhex[256] = break; default: - SET_ERRNO(HPE_CB_headers_complete); + CROW_SET_ERRNO(HPE_CB_headers_complete); return p - data; /* Error */ } } - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { return p - data; } @@ -1992,37 +1992,37 @@ static const int8_t unhex[256] = case s_headers_done: { - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->nread = 0; /* Exit, the rest of the connect is in a different protocol. */ if (parser->upgrade) { - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); return (p - data) + 1; } if (parser->flags & F_SKIPBODY) { - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); } else if (parser->flags & F_CHUNKED) { /* chunked encoding - ignore Content-Length header */ parser->state = s_chunk_size_start; } else { if (parser->content_length == 0) { /* Content-Length header given but zero: Content-Length: 0\r\n */ - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); - } else if (parser->content_length != ULLONG_MAX) { + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); + } else if (parser->content_length != CROW_ULLONG_MAX) { /* Content-Length header given and non-zero */ parser->state = s_body_identity; } else { if (parser->type == HTTP_REQUEST || !http_message_needs_eof(parser)) { /* Assume content-length 0 - read the next */ - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); } else { /* Read body until EOF */ parser->state = s_body_identity_eof; @@ -2035,25 +2035,25 @@ static const int8_t unhex[256] = case s_body_identity: { - uint64_t to_read = MIN(parser->content_length, + uint64_t to_read = CROW_MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); + && parser->content_length != CROW_ULLONG_MAX); /* The difference between advancing content_length and p is because * the latter will automaticaly advance on the next loop iteration. * Further, if content_length ends up at 0, we want to see the last * byte again for our message complete callback. */ - MARK(body); + CROW_MARK(body); parser->content_length -= to_read; p += to_read - 1; if (parser->content_length == 0) { parser->state = s_message_done; - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. + /* Mimic CROW_CALLBACK_DATA_NOADVANCE() but with one extra byte. * * The alternative to doing this is to wait for the next byte to * trigger the data callback, just as in every other case. The @@ -2062,7 +2062,7 @@ static const int8_t unhex[256] = * complete-on-length. It's not clear that this distinction is * important for applications, but let's keep it for now. */ - CALLBACK_DATA_(body, p - body_mark + 1, p - data); + CROW_CALLBACK_DATA_(body, p - body_mark + 1, p - data); goto reexecute_byte; } @@ -2071,14 +2071,14 @@ static const int8_t unhex[256] = /* read until EOF */ case s_body_identity_eof: - MARK(body); + CROW_MARK(body); p = data + len - 1; break; case s_message_done: - parser->state = NEW_MESSAGE(); - CALLBACK_NOTIFY(message_complete); + parser->state = CROW_NEW_MESSAGE(); + CROW_CALLBACK_NOTIFY(message_complete); break; case s_chunk_size_start: @@ -2088,7 +2088,7 @@ static const int8_t unhex[256] = unhex_val = unhex[(unsigned char)ch]; if (unhex_val == -1) { - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + CROW_SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } @@ -2103,7 +2103,7 @@ static const int8_t unhex[256] = assert(parser->flags & F_CHUNKED); - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_chunk_size_almost_done; break; } @@ -2116,7 +2116,7 @@ static const int8_t unhex[256] = break; } - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + CROW_SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } @@ -2125,8 +2125,8 @@ static const int8_t unhex[256] = t += unhex_val; /* Overflow? Test against a conservative limit for simplicity. */ - if ((ULLONG_MAX - 16) / 16 < parser->content_length) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + if ((CROW_ULLONG_MAX - 16) / 16 < parser->content_length) { + CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -2138,7 +2138,7 @@ static const int8_t unhex[256] = { assert(parser->flags & F_CHUNKED); /* just ignore this shit. TODO check for overflow */ - if (ch == CR) { + if (ch == CROW_CR) { parser->state = s_chunk_size_almost_done; break; } @@ -2148,7 +2148,7 @@ static const int8_t unhex[256] = case s_chunk_size_almost_done: { assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->nread = 0; @@ -2163,17 +2163,17 @@ static const int8_t unhex[256] = case s_chunk_data: { - uint64_t to_read = MIN(parser->content_length, + uint64_t to_read = CROW_MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->flags & F_CHUNKED); assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); + && parser->content_length != CROW_ULLONG_MAX); /* See the explanation in s_body_identity for why the content * length and data pointers are managed this way. */ - MARK(body); + CROW_MARK(body); parser->content_length -= to_read; p += to_read - 1; @@ -2187,21 +2187,21 @@ static const int8_t unhex[256] = case s_chunk_data_almost_done: assert(parser->flags & F_CHUNKED); assert(parser->content_length == 0); - STRICT_CHECK(ch != CR); + CROW_STRICT_CHECK(ch != CROW_CR); parser->state = s_chunk_data_done; - CALLBACK_DATA(body); + CROW_CALLBACK_DATA(body); break; case s_chunk_data_done: assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); + CROW_STRICT_CHECK(ch != CROW_LF); parser->nread = 0; parser->state = s_chunk_size_start; break; default: assert(0 && "unhandled state"); - SET_ERRNO(HPE_INVALID_INTERNAL_STATE); + CROW_SET_ERRNO(HPE_INVALID_INTERNAL_STATE); goto error; } } @@ -2212,7 +2212,7 @@ static const int8_t unhex[256] = * * We use the NOADVANCE() variety of callbacks here because 'p' has already * overflowed 'data' and this allows us to correct for the off-by-one that - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' + * we'd otherwise have (since CROW_CALLBACK_DATA() is meant to be run with a 'p' * value that's in-bounds). */ @@ -2222,17 +2222,17 @@ static const int8_t unhex[256] = (body_mark ? 1 : 0) + (status_mark ? 1 : 0)) <= 1); - CALLBACK_DATA_NOADVANCE(header_field); - CALLBACK_DATA_NOADVANCE(header_value); - CALLBACK_DATA_NOADVANCE(url); - CALLBACK_DATA_NOADVANCE(body); - CALLBACK_DATA_NOADVANCE(status); + CROW_CALLBACK_DATA_NOADVANCE(header_field); + CROW_CALLBACK_DATA_NOADVANCE(header_value); + CROW_CALLBACK_DATA_NOADVANCE(url); + CROW_CALLBACK_DATA_NOADVANCE(body); + CROW_CALLBACK_DATA_NOADVANCE(status); return len; error: - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { - SET_ERRNO(HPE_UNKNOWN); + if (CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK) { + CROW_SET_ERRNO(HPE_UNKNOWN); } return (p - data); @@ -2255,7 +2255,7 @@ http_message_needs_eof (const http_parser *parser) return 0; } - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { + if ((parser->flags & F_CHUNKED) || parser->content_length != CROW_ULLONG_MAX) { return 0; } @@ -2287,11 +2287,11 @@ http_method_str (enum http_method m) { static const char *method_strings[] = { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX +#define CROW_XX(num, name, string) #string, + CROW_HTTP_METHOD_MAP(CROW_XX) +#undef CROW_XX }; - return ELEM_AT(method_strings, m, ""); + return CROW_ELEM_AT(method_strings, m, ""); } @@ -2309,14 +2309,14 @@ http_parser_init (http_parser *parser, enum http_parser_type t) inline const char * http_errno_name(enum http_errno err) { /* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, +#define CROW_HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, static struct { const char *name; const char *description; } http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) + CROW_HTTP_ERRNO_MAP(CROW_HTTP_STRERROR_GEN) }; -#undef HTTP_STRERROR_GEN +#undef CROW_HTTP_STRERROR_GEN assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].name; } @@ -2324,14 +2324,14 @@ static struct { inline const char * http_errno_description(enum http_errno err) { /* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, +#define CROW_HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, static struct { const char *name; const char *description; } http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) + CROW_HTTP_ERRNO_MAP(CROW_HTTP_STRERROR_GEN) }; -#undef HTTP_STRERROR_GEN +#undef CROW_HTTP_STRERROR_GEN assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].description; } @@ -2345,7 +2345,7 @@ http_parse_host_char(enum http_host_state s, const char ch) { return s_http_host_start; } - if (IS_USERINFO_CHAR(ch)) { + if (CROW_IS_USERINFO_CHAR(ch)) { return s_http_userinfo; } break; @@ -2355,14 +2355,14 @@ http_parse_host_char(enum http_host_state s, const char ch) { return s_http_host_v6_start; } - if (IS_HOST_CHAR(ch)) { + if (CROW_IS_HOST_CHAR(ch)) { return s_http_host; } break; case s_http_host: - if (IS_HOST_CHAR(ch)) { + if (CROW_IS_HOST_CHAR(ch)) { return s_http_host; } @@ -2381,7 +2381,7 @@ http_parse_host_char(enum http_host_state s, const char ch) { /* FALLTHROUGH */ case s_http_host_v6_start: - if (IS_HEX(ch) || ch == ':' || ch == '.') { + if (CROW_IS_HEX(ch) || ch == ':' || ch == '.') { return s_http_host_v6; } @@ -2389,7 +2389,7 @@ http_parse_host_char(enum http_host_state s, const char ch) { case s_http_host_port: case s_http_host_port_start: - if (IS_NUM(ch)) { + if (CROW_IS_NUM(ch)) { return s_http_host_port; } @@ -2579,9 +2579,9 @@ http_parser_pause(http_parser *parser, int paused) { * state. In non-debug builds, there's not much that we can do about this * other than ignore it. */ - if (HTTP_PARSER_ERRNO(parser) == HPE_OK || - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); + if (CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK || + CROW_HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { + CROW_SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); } else { assert(0 && "Attempting to pause parser in error state"); } @@ -2594,45 +2594,45 @@ http_body_is_final(const struct http_parser *parser) { inline unsigned long http_parser_version(void) { - return HTTP_PARSER_VERSION_MAJOR * 0x10000 | - HTTP_PARSER_VERSION_MINOR * 0x00100 | - HTTP_PARSER_VERSION_PATCH * 0x00001; + return CROW_HTTP_PARSER_VERSION_MAJOR * 0x10000 | + CROW_HTTP_PARSER_VERSION_MINOR * 0x00100 | + CROW_HTTP_PARSER_VERSION_PATCH * 0x00001; } -#undef HTTP_METHOD_MAP -#undef HTTP_ERRNO_MAP -#undef SET_ERRNO -#undef CALLBACK_NOTIFY_ -#undef CALLBACK_NOTIFY -#undef CALLBACK_NOTIFY_NOADVANCE -#undef CALLBACK_DATA_ -#undef CALLBACK_DATA -#undef CALLBACK_DATA_NOADVANCE -#undef MARK -#undef PROXY_CONNECTION -#undef CONNECTION -#undef CONTENT_LENGTH -#undef TRANSFER_ENCODING -#undef UPGRADE -#undef CHUNKED -#undef KEEP_ALIVE -#undef CLOSE -#undef PARSING_HEADER -#undef CR -#undef LF -#undef LOWER -#undef IS_ALPHA -#undef IS_NUM -#undef IS_ALPHANUM -#undef IS_HEX -#undef IS_MARK -#undef IS_USERINFO_CHAR -#undef TOKEN -#undef IS_URL_CHAR -#undef IS_HOST_CHAR -#undef start_state -#undef STRICT_CHECK -#undef NEW_MESSAGE +#undef CROW_HTTP_METHOD_MAP +#undef CROW_HTTP_ERRNO_MAP +#undef CROW_SET_ERRNO +#undef CROW_CALLBACK_NOTIFY_ +#undef CROW_CALLBACK_NOTIFY +#undef CROW_CALLBACK_NOTIFY_NOADVANCE +#undef CROW_CALLBACK_DATA_ +#undef CROW_CALLBACK_DATA +#undef CROW_CALLBACK_DATA_NOADVANCE +#undef CROW_MARK +#undef CROW_PROXY_CONNECTION +#undef CROW_CONNECTION +#undef CROW_CONTENT_LENGTH +#undef CROW_TRANSFER_ENCODING +#undef CROW_UPGRADE +#undef CROW_CHUNKED +#undef CROW_KEEP_ALIVE +#undef CROW_CLOSE +#undef CROW_PARSING_HEADER +#undef CROW_CR +#undef CROW_LF +#undef CROW_LOWER +#undef CROW_IS_ALPHA +#undef CROW_IS_NUM +#undef CROW_IS_ALPHANUM +#undef CROW_IS_HEX +#undef CROW_IS_MARK +#undef CROW_IS_USERINFO_CHAR +#undef CROW_TOKEN +#undef CROW_IS_URL_CHAR +#undef CROW_IS_HOST_CHAR +#undef CROW_start_state +#undef CROW_STRICT_CHECK +#undef CROW_NEW_MESSAGE #ifdef __cplusplus } diff --git a/ext/crow/http_request.h b/ext/crow/http_request.h old mode 100644 new mode 100755 index 75bce73..535a1fd --- a/ext/crow/http_request.h +++ b/ext/crow/http_request.h @@ -3,6 +3,7 @@ #include "common.h" #include "ci_map.h" #include "query_string.h" +#include 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 + void post(CompletionHandler handler) + { + io_service->post(handler); + } + + template + void dispatch(CompletionHandler handler) + { + io_service->dispatch(handler); + } + }; } diff --git a/ext/crow/http_response.h b/ext/crow/http_response.h old mode 100644 new mode 100755 index a7b63bf..23f312a --- a/ext/crow/http_response.h +++ b/ext/crow/http_response.h @@ -14,9 +14,9 @@ namespace crow template 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 complete_request_handler_; std::function is_alive_helper_; - + //In case of a JSON object, set the Content-Type header void json_mode() { diff --git a/ext/crow/http_server.h b/ext/crow/http_server.h old mode 100644 new mode 100755 index 80ef7a4..86943ee --- a/ext/crow/http_server.h +++ b/ext/crow/http_server.h @@ -20,17 +20,18 @@ namespace crow { using namespace boost; using tcp = asio::ip::tcp; - + template class Server { public: - Server(Handler* handler, uint16_t port, std::tuple* 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 = 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> v; + std::atomic 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_; diff --git a/ext/crow/json.h b/ext/crow/json.h old mode 100644 new mode 100755 index 58457e3..9f06244 --- a/ext/crow/json.h +++ b/ext/crow/json.h @@ -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(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(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(start_, end_-start_); + default: + throw std::runtime_error(std::string("expected number, got: ") + get_type_str(t())); + } +#endif + return boost::lexical_cast(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>(new std::vector{})); + l = std::unique_ptr>(new std::vector{}); 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 >( - new std::unordered_map{})); + new std::unordered_map{}); 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>(new std::vector{})); + l = std::unique_ptr>(new std::vector{}); 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>(new std::vector{})); + l = std::unique_ptr>(new std::vector{}); 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 >( - new std::unordered_map{})); + new std::unordered_map{}); return (*o)[str]; } diff --git a/ext/crow/logging.h b/ext/crow/logging.h old mode 100644 new mode 100755 index b915e6e..13cdad2 --- a/ext/crow/logging.h +++ b/ext/crow/logging.h @@ -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) diff --git a/ext/crow/middleware.h b/ext/crow/middleware.h old mode 100644 new mode 100755 index ec54476..534a87a --- a/ext/crow/middleware.h +++ b/ext/crow/middleware.h @@ -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) { diff --git a/ext/crow/mustache.h b/ext/crow/mustache.h old mode 100644 new mode 100755 index b596b45..279f356 --- a/ext/crow/mustache.h +++ b/ext/crow/mustache.h @@ -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(inf), std::istreambuf_iterator()}; diff --git a/ext/crow/parser.h b/ext/crow/parser.h old mode 100644 new mode 100755 index f6b748b..b621850 --- a/ext/crow/parser.h +++ b/ext/crow/parser.h @@ -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; diff --git a/ext/crow/routing.h b/ext/crow/routing.h old mode 100644 new mode 100755 index 3261134..4fc2de8 --- a/ext/crow/routing.h +++ b/ext/crow/routing.h @@ -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 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 rule_to_upgrade_; + friend class Router; template 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(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(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_); + } +#endif + + template + self_t& onopen(Func f) + { + open_handler_ = f; + return *this; + } + + template + self_t& onmessage(Func f) + { + message_handler_ = f; + return *this; + } + + template + self_t& onclose(Func f) + { + close_handler_ = f; + return *this; + } + + template + self_t& onerror(Func f) + { + error_handler_ = f; + return *this; + } + + protected: + std::function open_handler_; + std::function message_handler_; + std::function close_handler_; + std::function error_handler_; + }; + template 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 @@ -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 + 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); diff --git a/ext/crow/socket_adaptors.h b/ext/crow/socket_adaptors.h old mode 100644 new mode 100755 index 201360c..634bd4b --- a/ext/crow/socket_adaptors.h +++ b/ext/crow/socket_adaptors.h @@ -1,5 +1,8 @@ #pragma once #include +#ifdef CROW_ENABLE_SSL +#include +#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; 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& 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 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 ssl_socket_; + std::unique_ptr> ssl_socket_; }; #endif } diff --git a/ext/crow/utility.h b/ext/crow/utility.h old mode 100644 new mode 100755 index cf12158..b714d55 --- a/ext/crow/utility.h +++ b/ext/crow/utility.h @@ -6,6 +6,7 @@ #include #include #include +#include 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 \ { \ 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 using arg = typename std::tuple_element>::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 } diff --git a/main.cpp b/main.cpp index 4497486..f4185c5 100644 --- a/main.cpp +++ b/main.cpp @@ -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 diff --git a/src/MicroCore.cpp b/src/MicroCore.cpp index eb3eb04..6fa0bcc 100644 --- a/src/MicroCore.cpp +++ b/src/MicroCore.cpp @@ -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); } /** diff --git a/src/MicroCore.h b/src/MicroCore.h index facdab1..4255c22 100644 --- a/src/MicroCore.h +++ b/src/MicroCore.h @@ -11,7 +11,6 @@ #include "tx_details.h" - namespace xmreg { using namespace cryptonote; diff --git a/src/monero_headers.h b/src/monero_headers.h index 1ee0611..937ff46 100644 --- a/src/monero_headers.h +++ b/src/monero_headers.h @@ -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"