diff --git a/cmake/config.h.in b/cmake/config.h.in new file mode 100644 index 0000000..0aaf0e7 --- /dev/null +++ b/cmake/config.h.in @@ -0,0 +1,30 @@ +#pragma once + +#cmakedefine CPPMICROHTTPD_DEBUG +#cmakedefine CPPMICROHTTPD_LOGGING_NONE +#cmakedefine CPPMICROHTTPD_LOGGING_STDCOUT +#cmakedefine CPPMICROHTTPD_LOGGING_CPPLOGGING + +#if defined(CPPMICROHTTPD_LOGGING_CPPLOGGING) + #include + #define cppmicrohttpd_log(p_level) \ + cpplogging_global_log(p_level) + #define cppmicrohttpd_log_debug(...) \ + cppmicrohttpd_log(debug) << __VA_ARGS__ +#elif defined(CPPMICROHTTPD_LOGGING_STDCOUT) + #include + #define cppmicrohttpd_log(p_level) \ + ::std::cout << #p_level << ' ' << __FILE__ << ':' << __LINE__ << " - " + #ifdef CPPMICROHTTPD_DEBUG + #define cppmicrohttpd_log_debug(...) \ + cppmicrohttpd_log(debug) << __VA_ARGS__ + #else + #define cppmicrohttpd_log_debug(...) \ + do { } while (0) + #endif +#else + #define cppmicrohttpd_log(...) \ + do { } while (0) + #define cppmicrohttpd_log_debug(...) \ + do { } while (0) +#endif diff --git a/cmake/cppmicrohttpd-options.cmake b/cmake/cppmicrohttpd-options.cmake index efef207..2d10276 100644 --- a/cmake/cppmicrohttpd-options.cmake +++ b/cmake/cppmicrohttpd-options.cmake @@ -10,6 +10,9 @@ Option ( CPPMICROHTTPD_INSTALL_SHARED Option ( CPPMICROHTTPD_INSTALL_DEBUG "Install the stripped debug informations of cppmicrohttpd." OFF ) -Option ( CPPMICROHTTPD_NO_STRIP - "Do not strip debug symbols from binary." - OFF ) +If ( NOT CPPMICROHTTPD_LOGGING ) + Set ( CPPMICROHTTPD_LOGGING none + CACHE STRING "Specify how cppmicrohttpd should write log entries." ) + Set_Property ( CACHE CPPMICROHTTPD_LOGGING + PROPERTY STRINGS none stdout cpplogging ) +EndIf ( ) diff --git a/include/cppmicrohttpd/daemon.h b/include/cppmicrohttpd/daemon.h index 00f8ff4..45c2db9 100644 --- a/include/cppmicrohttpd/daemon.h +++ b/include/cppmicrohttpd/daemon.h @@ -2,6 +2,7 @@ #include #include +#include #include "types.h" #include "request/request.h" @@ -52,22 +53,28 @@ namespace cppmicrohttpd /** * @brief Run webserver operations using the given sets of ready socket handles. * - * @param[in] read File descriptor set with all file handles that are ready to read data from. - * @param[in] write File descriptor set with all file handles that are ready to write data to. - * @param[in] except File descriptor set with all file handles that are in a exceptional condition. + * @param[in] p_read File descriptor set with all file handles that are ready to read data from. + * @param[in] p_write File descriptor set with all file handles that are ready to write data to. + * @param[in] p_except File descriptor set with all file handles that are in a exceptional condition. */ - inline void run(const fd_set& read, const fd_set& write, const fd_set& except); + inline void run( + const ::cppcore::fdset& p_read, + const ::cppcore::fdset& p_write, + const ::cppcore::fdset& p_except); /** * @brief Write all file descriptors known by the daemon to the passed file descriptor sets. * - * @param[in] read File descriptor set to listen for read operations. - * @param[in] write File descriptor set to listen for write operations. - * @param[in] except File descriptor set to listen for exceptional condition. + * @param[in] p_read File descriptor set to listen for read operations. + * @param[in] p_write File descriptor set to listen for write operations. + * @param[in] p_except File descriptor set to listen for exceptional condition. * * @return Greatest file descriptor. */ - inline int prepare_fd_sets(fd_set& read, fd_set& write, fd_set& except) const; + inline int prepare_fdsets( + ::cppcore::fdset& p_read, + ::cppcore::fdset& p_write, + ::cppcore::fdset& p_except) const; /** * @brief Get the timeout in milliseconds to wait for the file descriptors. @@ -103,6 +110,18 @@ namespace cppmicrohttpd virtual response_ptr_u create_response( const request& p_request); + /** + * @brief Create a default response object. + * + * @param[in] p_request Request to create response for. + * @param[in] p_error_only Only create responses for erroneous request. + * + * @return Created request or null if no request could be created. + */ + response_ptr_u create_default_response( + const request& p_request, + bool p_error_only); + public: /** * @brief Callback to handle requests. diff --git a/include/cppmicrohttpd/daemon.inl b/include/cppmicrohttpd/daemon.inl index 12aa4e3..b8e14b1 100644 --- a/include/cppmicrohttpd/daemon.inl +++ b/include/cppmicrohttpd/daemon.inl @@ -16,16 +16,22 @@ namespace cppmicrohttpd throw exception("Unable to execute MHD_run"); } - void daemon::run(const fd_set& read, const fd_set& write, const fd_set& except) + void daemon::run( + const ::cppcore::fdset& p_read, + const ::cppcore::fdset& p_write, + const ::cppcore::fdset& p_except) { - if (MHD_run_from_select(_handle.get(), &read, &write, &except) != MHD_YES) + if (MHD_run_from_select(_handle.get(), &p_read, &p_write, &p_except) != MHD_YES) throw exception("Unable to execute MHD_run_from_select"); } - int daemon::prepare_fd_sets(fd_set& read, fd_set& write, fd_set& except) const + int daemon::prepare_fdsets( + ::cppcore::fdset& p_read, + ::cppcore::fdset& p_write, + ::cppcore::fdset& p_except) const { int ret = 0; - if (MHD_get_fdset(_handle.get(), &read, &write, &except, &ret) != MHD_YES) + if (MHD_get_fdset(_handle.get(), &p_read, &p_write, &p_except, &ret) != MHD_YES) throw exception("Unable to execute MHD_get_fdset"); return ret; } diff --git a/include/cppmicrohttpd/request/request.h b/include/cppmicrohttpd/request/request.h index 14f5e0a..b66e16b 100644 --- a/include/cppmicrohttpd/request/request.h +++ b/include/cppmicrohttpd/request/request.h @@ -20,7 +20,7 @@ namespace cppmicrohttpd struct request { private: - using exception_ptr_u = std::unique_ptr; + using exception_ptr_u = std::unique_ptr; public: MHD_Connection * const connection; //!< Connection this request was received at. diff --git a/include/cppmicrohttpd/types.h b/include/cppmicrohttpd/types.h index b456817..83c33e7 100644 --- a/include/cppmicrohttpd/types.h +++ b/include/cppmicrohttpd/types.h @@ -60,7 +60,7 @@ namespace cppmicrohttpd use_pedantic_checks = MHD_USE_PEDANTIC_CHECKS, /** - * Use poll() instead of select(). This allows sockets with descriptors >= FD_SETSIZE. This option currently only + * Use poll() instead of select(). This allows sockets with descriptors >= ::cppcore::fdsetSIZE. This option currently only * works in conjunction with MHD_USE_THREAD_PER_CONNECTION or MHD_USE_INTERNAL_SELECT (at this point). * If you specify MHD_USE_POLL and the local platform does not support it, MHD_start_daemon will return NULL. */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6bd120c..fd61b07 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,11 +5,26 @@ Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTI Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS ) Find_Package ( cppcore REQUIRED ) +Find_Package ( libmicrohttpd REQUIRED ) + +If ( CPPMICROHTTPD_LOGGING MATCHES none ) + Set ( CPPMICROHTTPD_LOGGING_NONE true ) +ElseIf ( CPPMICROHTTPD_LOGGING MATCHES stdcout ) + Set ( CPPMICROHTTPD_LOGGING_STDCOUT true ) +ElseIf ( CPPMICROHTTPD_LOGGING MATCHES cpplogging ) + Find_Package ( cpplogging QUIET ) + If ( cpplogging_FOUND ) + Set ( CPPMICROHTTPD_LOGGING_CPPLOGGING true ) + EndIf ( ) +EndIf ( ) # Object Library ################################################################################## Set ( CMAKE_POSITION_INDEPENDENT_CODE ON ) Set ( CPPMICROHTTPD_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) +Set ( CPPMICROHTTPD_GENERATED_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include ) +Configure_File ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/config.h.in + ${CPPMICROHTTPD_GENERATED_INCLUDE_DIR}/cppmicrohttpd/config.h ) File ( GLOB_RECURSE CPPMICROHTTPD_HEADER_FILES ${CPPMICROHTTPD_INCLUDE_DIR}/*.h ) File ( GLOB_RECURSE CPPMICROHTTPD_INLINE_FILES ${CPPMICROHTTPD_INCLUDE_DIR}/*.inl ) File ( GLOB_RECURSE CPPMICROHTTPD_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) @@ -21,10 +36,16 @@ Add_Library ( cppmicrohttpd-objects Target_Include_Directories ( cppmicrohttpd-objects PUBLIC $ + $ $ ) Target_Link_Libraries ( cppmicrohttpd-objects PUBLIC cppcore::cppcore ) +If ( CPPMICROHTTPD_LOGGING_CPPLOGGING ) + Target_Link_Libraries ( cppmicrohttpd-objects + PUBLIC + cpplogging::cpplogging-shared ) +EndIf ( ) # Static Library ################################################################################## @@ -36,10 +57,17 @@ Set_Target_Properties ( cppmicrohttpd-static Target_Include_Directories ( cppmicrohttpd-static PUBLIC $ + $ $ ) Target_Link_Libraries ( cppmicrohttpd-static PUBLIC - cppcore::cppcore ) + cppcore::cppcore + libmicrohttpd::libmicrohttpd-static ) +If ( CPPMICROHTTPD_LOGGING_CPPLOGGING ) + Target_Link_Libraries ( cppmicrohttpd-static + PUBLIC + cpplogging::cpplogging-static ) +EndIf ( ) # Shared Library ################################################################################## @@ -52,10 +80,17 @@ Set_Target_Properties ( cppmicrohttpd-shared Target_Include_Directories ( cppmicrohttpd-shared PUBLIC $ + $ $ ) Target_Link_Libraries ( cppmicrohttpd-shared PUBLIC - cppcore::cppcore ) + cppcore::cppcore + libmicrohttpd::libmicrohttpd-shared ) +If ( CPPMICROHTTPD_LOGGING_CPPLOGGING ) + Target_Link_Libraries ( cppmicrohttpd-shared + PUBLIC + cpplogging::cpplogging-shared ) +EndIf ( ) # Optimization #################################################################################### @@ -81,6 +116,8 @@ If ( CPPMICROHTTPD_INSTALL_HEADER ) DESTINATION ${CPPMICROHTTPD_INSTALL_DIR_INCLUDE} ) Install ( DIRECTORY ${CPPMICROHTTPD_INCLUDE_DIR}/cppmicrohttpd DESTINATION ${CPPMICROHTTPD_INSTALL_DIR_INCLUDE} ) + Install ( DIRECTORY ${CPPMICROHTTPD_GENERATED_INCLUDE_DIR}/cppmicrohttpd + DESTINATION ${CPPMICROHTTPD_INSTALL_DIR_INCLUDE} ) EndIf ( ) # Static diff --git a/src/cppmicrohttpd/damon.cpp b/src/cppmicrohttpd/damon.cpp index 36258f5..72bfacf 100644 --- a/src/cppmicrohttpd/damon.cpp +++ b/src/cppmicrohttpd/damon.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include @@ -37,21 +39,53 @@ request_ptr_u daemon::create_request( response_ptr_u daemon::create_response( const request& p_request) + { return create_default_response(p_request, true); } + +response_ptr_u daemon::create_default_response( + const request& p_request, + bool p_error_only) { + using namespace ::std; + if (p_request.error) { - /* TODO - auto err = *request.httpError; - return Response::buildSimpleHtmlResponse( - request, - err.status, - err.title, - err.head, - err.message); - */ + auto* http_ex = dynamic_cast(p_request.error.get()); + auto* core_ex = dynamic_cast(p_request.error.get()); + if (http_ex) + { + return response::build_simple_html_response( + p_request, + http_ex->status, + "Status "s + ::cppcore::to_string(http_ex->status), + "Status "s + ::cppcore::to_string(http_ex->status), + http_ex->print(::cppcore::exception::print_flags::empty())); + } + else if (core_ex) + { + return response::build_simple_html_response( + p_request, + 500, + "Status 500"s, + "Status 500"s, + core_ex->print(::cppcore::exception::print_flags::empty())); + } + else + { + return response::build_simple_html_response( + p_request, + 500, + "Status 500"s, + "Status 500"s, + "Unknown error. Check server error log."); + } } - return nullptr; + return response::build_simple_html_response( + p_request, + 404, + "Status 404"s, + "Status 404"s, + "The requested URL could not be found on this server: "s + p_request.url); } int daemon::mhd_access_handler_callback( @@ -86,9 +120,14 @@ int daemon::mhd_access_handler_callback( return MHD_YES; } } + catch(const std::exception& ex) + { + cppmicrohttpd_log(error) << "Error while creating request: " << ex.what(); + return MHD_NO; + } catch(...) { - // TODO: log error + cppmicrohttpd_log(error) << "Error while creating request: unknown"; return MHD_NO; } @@ -103,26 +142,28 @@ int daemon::mhd_access_handler_callback( } catch(const http_exception& ex) { + cppmicrohttpd_log(warn) << "Error while handling post data: " << ex; req.set_error(ex); *data_size = 0; // Assume that all data has been progressed return MHD_YES; } catch(const exception& ex) { + cppmicrohttpd_log(warn) << "Error while handling post data: " << ex; req.set_error(ex); *data_size = 0; // Assume that all data has been progressed return MHD_YES; } catch(std::exception& ex) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while handling post data: " << ex.what(); req.set_error(exception(ex.what())); *data_size = 0; // Assume that all data has been progressed return MHD_YES; } catch(...) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while handling post data: unknown"; req.set_error(exception("Unknown error")); *data_size = 0; // Assume that all data has been progressed return MHD_YES; @@ -144,9 +185,14 @@ int daemon::mhd_access_handler_callback( } return MHD_YES; } + catch(const std::exception& ex) + { + cppmicrohttpd_log(error) << "Error while creating response: " << ex.what(); + return MHD_NO; + } catch(...) { - // TODO log error + cppmicrohttpd_log(error) << "Error while creating response: unknown"; return MHD_NO; } } diff --git a/src/cppmicrohttpd/request/post_data_request.cpp b/src/cppmicrohttpd/request/post_data_request.cpp index a270432..85a5303 100644 --- a/src/cppmicrohttpd/request/post_data_request.cpp +++ b/src/cppmicrohttpd/request/post_data_request.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -57,23 +58,23 @@ int post_data_request::mhd_post_data_iterator_callback( } catch(const http_exception& ex) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while iterating post data: " << ex; req.set_error(ex); } catch(const exception& ex) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while iterating post data: " << ex; req.set_error(ex); } catch(const std::exception& ex) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while iterating post data: " << ex.what(); req.set_error(exception(ex.what())); } catch(...) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while iterating post data: unknown"; req.set_error(exception("Unknown error")); } - return MHD_YES; + return MHD_NO; } diff --git a/src/cppmicrohttpd/response/callback_response.cpp b/src/cppmicrohttpd/response/callback_response.cpp index 0a1e54c..c9a9837 100644 --- a/src/cppmicrohttpd/response/callback_response.cpp +++ b/src/cppmicrohttpd/response/callback_response.cpp @@ -1,3 +1,4 @@ +#include #include using namespace ::cppmicrohttpd; @@ -16,9 +17,13 @@ ssize_t callback_response::mhd_content_reader_callback( { return res.read_content(pos, buf, max); } + catch(const std::exception& ex) + { + cppmicrohttpd_log(warn) << "Error while generating response data: " << ex.what(); + } catch(...) { - // TODO log error + cppmicrohttpd_log(warn) << "Error while generating response data: unknown"; } /** diff --git a/test/helper/libmicrohttpd_mock.cpp b/test/helper/libmicrohttpd_mock.cpp index 3cd16c8..87ae2c9 100644 --- a/test/helper/libmicrohttpd_mock.cpp +++ b/test/helper/libmicrohttpd_mock.cpp @@ -7,14 +7,14 @@ extern "C" int MHD_get_fdset2( struct MHD_Daemon *daemon, - fd_set * read_fd_set, - fd_set * write_fd_set, - fd_set * except_fd_set, + ::cppcore::fdset * read_::cppcore::fdset, + ::cppcore::fdset * write_::cppcore::fdset, + ::cppcore::fdset * except_::cppcore::fdset, int * max_fd, - unsigned int fd_setsize) + unsigned int ::cppcore::fdsetsize) { return libmicrohttpd_mock::instance - ? libmicrohttpd_mock::instance->MHD_get_fdset2(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd, fd_setsize) + ? libmicrohttpd_mock::instance->MHD_get_fdset2(daemon, read_::cppcore::fdset, write_::cppcore::fdset, except_::cppcore::fdset, max_fd, ::cppcore::fdsetsize) : MHD_NO; } @@ -29,12 +29,12 @@ extern "C" int MHD_run_from_select ( struct MHD_Daemon * daemon, - const fd_set * read_fd_set, - const fd_set * write_fd_set, - const fd_set * except_fd_set) + const ::cppcore::fdset * read_::cppcore::fdset, + const ::cppcore::fdset * write_::cppcore::fdset, + const ::cppcore::fdset * except_::cppcore::fdset) { return libmicrohttpd_mock::instance - ? libmicrohttpd_mock::instance->MHD_run_from_select(daemon, read_fd_set, write_fd_set, except_fd_set) + ? libmicrohttpd_mock::instance->MHD_run_from_select(daemon, read_::cppcore::fdset, write_::cppcore::fdset, except_::cppcore::fdset) : MHD_NO; } diff --git a/test/helper/libmicrohttpd_mock.h b/test/helper/libmicrohttpd_mock.h index f7a145f..fddd0b6 100644 --- a/test/helper/libmicrohttpd_mock.h +++ b/test/helper/libmicrohttpd_mock.h @@ -10,11 +10,11 @@ public: MOCK_METHOD6( MHD_get_fdset2, int (struct MHD_Daemon *daemon, - fd_set * read_fd_set, - fd_set * write_fd_set, - fd_set * except_fd_set, + ::cppcore::fdset * read_::cppcore::fdset, + ::cppcore::fdset * write_::cppcore::fdset, + ::cppcore::fdset * except_::cppcore::fdset, int * max_fd, - unsigned int fd_setsize)); + unsigned int ::cppcore::fdsetsize)); MOCK_METHOD2( MHD_get_timeout, @@ -24,9 +24,9 @@ public: MOCK_METHOD4( MHD_run_from_select, int (struct MHD_Daemon * daemon, - const fd_set * read_fd_set, - const fd_set * write_fd_set, - const fd_set * except_fd_set)); + const ::cppcore::fdset * read_::cppcore::fdset, + const ::cppcore::fdset * write_::cppcore::fdset, + const ::cppcore::fdset * except_::cppcore::fdset)); MOCK_METHOD6( MHD_start_daemon,