diff --git a/.travis.yml b/.travis.yml index fc067d77..71a01ec0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,9 @@ compiler: # Change this to your needs before_install: - sudo apt-get install texinfo - - wget http://199.231.187.83/resources/libmicrohttpd-0.9.26.tar.gz - - tar -xvzf libmicrohttpd-0.9.26.tar.gz - - cd libmicrohttpd-0.9.26 + - wget ftp://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.37.tar.gz + - tar -xvzf libmicrohttpd-0.9.37.tar.gz + - cd libmicrohttpd-0.9.37 - ./configure --prefix=/usr - make - sudo make install diff --git a/README.md b/README.md index 278e70cd..0a1ad396 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,10 @@ Requirements * libmicrohttpd >= 0.9.7 * doxygen (if you want to build code reference) +Additionally, for MinGW on windows you will need: +* libwinpthread (For MinGW-w64, if you use thread model posix then you have this) +* libgnurx >= 2.5.1 + Compilation =========== libhttpserver uses the standard system where the usual build process diff --git a/configure.ac b/configure.ac index 6130202f..c3333227 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ m4_define([libhttpserver_REVISION],[2])dnl m4_define([libhttpserver_PKG_VERSION],[libhttpserver_MAJOR_VERSION.libhttpserver_MINOR_VERSION.libhttpserver_REVISION])dnl m4_define([libhttpserver_LDF_VERSION],[libhttpserver_MAJOR_VERSION:libhttpserver_MINOR_VERSION:libhttpserver_REVISION])dnl AC_INIT([libhttpserver], libhttpserver_PKG_VERSION, [electrictwister2000@gmail.com]) -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([subdir-objects]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) @@ -53,6 +53,21 @@ if test x"$samedirectory" = x"no"; then fi fi +case "$host" in + *-mingw*) + NETWORK_HEADER="winsock2.h" + REGEX_LIBS="-lregex -no-undefined" + ;; + *-cygwin*) + NETWORK_HEADER="winsock2.h" + REGEX_LIBS="-lregex -no-undefined" + ;; + *) + NETWORK_HEADER="arpa/inet.h" + REGEX_LIBS="" + ;; +esac + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADER([string],[],[AC_MSG_ERROR("C++ strings not found")]) @@ -73,7 +88,7 @@ AC_CHECK_HEADER([ctype.h],[],[AC_MSG_ERROR("cctype not found")]) AC_CHECK_HEADER([regex.h],[],[AC_MSG_ERROR("regex.h not found")]) AC_CHECK_HEADER([sys/stat.h],[],[AC_MSG_ERROR("sys/stat.h not found")]) AC_CHECK_HEADER([sys/types.h],[],[AC_MSG_ERROR("sys/types.h not found")]) -AC_CHECK_HEADER([arpa/inet.h],[],[AC_MSG_ERROR("arpa/inet.h not found")]) +AC_CHECK_HEADER([$NETWORK_HEADER],[],[AC_MSG_ERROR("$NETWORK_HEADER not found")]) AC_CHECK_HEADER([signal.h],[],[AC_MSG_ERROR("signal.h not found")]) AC_CHECK_HEADER([gnutls/gnutls.h],[have_gnutls="yes"],[AC_MSG_WARN("gnutls/gnutls.h not found. TLS will be disabled"); have_gnutls="no"]) @@ -84,7 +99,7 @@ PKG_CHECK_MODULES([LIBMICROHTTPD],[libmicrohttpd >= 0.9.7],[],[AC_MSG_ERROR("lib #AC_CHECK_LIB([microhttpd],[MHD_start_daemon],[],[AC_MSG_ERROR("Microhttpd header files not found. Please use a version >= 0.9.9.")]) CXXFLAGS="-DHTTPSERVER_COMPILATION -D_REENTRANT $LIBMICROHTTPD_CFLAGS $CXXFLAGS" -LDFLAGS="$LIBMICROHTTPD_LIBS $LD_FLAGS" +LDFLAGS="$LIBMICROHTTPD_LIBS $REGEX_LIBS $LD_FLAGS" m4_pattern_allow([AC_TYPE_SIZE_T]) m4_pattern_allow([AC_TYPE_UINT16_T]) diff --git a/src/Makefile.am b/src/Makefile.am index c7681d3f..c88305f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ AM_CXXFLAGS += -fPIC -Wall libhttpserver_la_LIBADD = -lmicrohttpd libhttpserver_la_LDFLAGS = -install-exec-hook: +install-data-hook: (mkdir -p $(DESTDIR)$(includedir) && cd $(DESTDIR)$(includedir) && $(LN_S) -f httpserver.hpp httpserverpp) uninstall-hook: diff --git a/src/details/comet_manager.cpp b/src/details/comet_manager.cpp index c3b42640..d9d13adf 100644 --- a/src/details/comet_manager.cpp +++ b/src/details/comet_manager.cpp @@ -21,6 +21,7 @@ #include #include #include "details/comet_manager.hpp" +#include using namespace std; @@ -140,7 +141,7 @@ size_t comet_manager::get_topic_consumers( { consumers.insert((*it)); } - int size = consumers.size(); + std::set::size_type size = consumers.size(); pthread_rwlock_unlock(&comet_guard); return size; } diff --git a/src/details/http_endpoint.cpp b/src/details/http_endpoint.cpp index 59afa375..1fa7e059 100644 --- a/src/details/http_endpoint.cpp +++ b/src/details/http_endpoint.cpp @@ -99,8 +99,8 @@ http_endpoint::http_endpoint (parts[i][parts[i].size() - 1] == '}') ) { - int bar = parts[i].find_first_of('|'); - if(bar != (int)string::npos) + std::string::size_type bar = parts[i].find_first_of('|'); + if(bar != string::npos) { this->url_pars.push_back(parts[i].substr(1, bar - 1)); if(first) @@ -201,7 +201,7 @@ http_endpoint& http_endpoint::operator =(const http_endpoint& h) bool http_endpoint::operator <(const http_endpoint& b) const { - COMPARATOR(this->url_modded, b.url_modded, toupper); + COMPARATOR(this->url_modded, b.url_modded, std::toupper); } bool http_endpoint::match(const http_endpoint& url) const diff --git a/src/http_response.cpp b/src/http_response.cpp index d2eaf1be..d086e15e 100644 --- a/src/http_response.cpp +++ b/src/http_response.cpp @@ -207,7 +207,7 @@ namespace details ssize_t cb(void* cls, uint64_t pos, char* buf, size_t max) { - int val = static_cast(cls)->cycle_callback(buf); + ssize_t val = static_cast(cls)->cycle_callback(buf); if(val == -1) static_cast(cls)->completed = true; return val; @@ -272,7 +272,7 @@ ssize_t http_response::data_generator( if(_this->ws->pop_signaled(_this->connection_id)) { string message; - int size = _this->ws->read_message(_this->connection_id, message); + size_t size = _this->ws->read_message(_this->connection_id, message); memcpy(buf, message.c_str(), size); return size; } diff --git a/src/http_utils.cpp b/src/http_utils.cpp index 74d00629..96c05df0 100644 --- a/src/http_utils.cpp +++ b/src/http_utils.cpp @@ -21,7 +21,15 @@ #include #include #include +#if defined(__MINGW32__) || defined(__CYGWIN32__) +#define _WINDOWS +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x600 +#include +#include +#else #include +#endif #include #include #include diff --git a/src/httpserver/create_webserver.hpp b/src/httpserver/create_webserver.hpp index 0c6582b3..262a02e4 100644 --- a/src/httpserver/create_webserver.hpp +++ b/src/httpserver/create_webserver.hpp @@ -85,7 +85,7 @@ class create_webserver { } - explicit create_webserver(int port): + explicit create_webserver(uint16_t port): _port(port), _start_method(http::http_utils::INTERNAL_SELECT), _max_threads(0), @@ -125,7 +125,7 @@ class create_webserver { } - create_webserver& port(int port) { _port = port; return *this; } + create_webserver& port(uint16_t port) { _port = port; return *this; } create_webserver& start_method( const http::http_utils::start_method_T& start_method ) @@ -317,7 +317,7 @@ class create_webserver } private: - int _port; + uint16_t _port; http::http_utils::start_method_T _start_method; int _max_threads; int _max_connections; diff --git a/src/httpserver/details/event_tuple.hpp b/src/httpserver/details/event_tuple.hpp index ec289120..a81ca7b9 100644 --- a/src/httpserver/details/event_tuple.hpp +++ b/src/httpserver/details/event_tuple.hpp @@ -42,7 +42,7 @@ namespace details fd_set*, fd_set*, fd_set*, - int* + MHD_socket* ); typedef struct timeval(*get_timeout_ptr)(); diff --git a/src/httpserver/event_supplier.hpp b/src/httpserver/event_supplier.hpp index 6835050e..9c7e223b 100644 --- a/src/httpserver/event_supplier.hpp +++ b/src/httpserver/event_supplier.hpp @@ -43,7 +43,7 @@ class event_supplier fd_set* read_fdset, fd_set* write_fdset, fd_set* exc_fdset, - int* max + MHD_socket* max ) const { static_cast(this)->supply_events( diff --git a/src/httpserver/http_utils.hpp b/src/httpserver/http_utils.hpp index deccc180..9707aca9 100644 --- a/src/httpserver/http_utils.hpp +++ b/src/httpserver/http_utils.hpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -238,8 +238,8 @@ class http_utils \ for (size_t n = 0; n < l1; n++)\ {\ - char xc = op((x)[n]);\ - char yc = op((y)[n]);\ + int xc = op((x)[n]);\ + int yc = op((y)[n]);\ if (xc < yc) return true;\ if (xc > yc) return false;\ }\ @@ -255,7 +255,7 @@ class header_comparator { **/ bool operator()(const std::string& x,const std::string& y) const { - COMPARATOR(x, y, toupper); + COMPARATOR(x, y, std::toupper); } }; @@ -274,7 +274,7 @@ class arg_comparator { bool operator()(const std::string& x,const std::string& y) const { #ifdef CASE_INSENSITIVE - COMPARATOR(x, y, toupper); + COMPARATOR(x, y, std::toupper); #else COMPARATOR(x, y, ); #endif diff --git a/src/httpserver/webserver.hpp b/src/httpserver/webserver.hpp index 305cf0d9..55591524 100644 --- a/src/httpserver/webserver.hpp +++ b/src/httpserver/webserver.hpp @@ -188,7 +188,7 @@ class webserver webserver& operator=(const webserver& other); private: - const int port; + const uint16_t port; http::http_utils::start_method_T start_method; const int max_threads; const int max_connections; @@ -200,7 +200,9 @@ class webserver validator_ptr validator; unescaper_ptr unescaper; const struct sockaddr* bind_address; - int bind_socket; + /* Changed type to MHD_socket because this type will always reflect the + platform's actual socket type (e.g. SOCKET on windows, int on unixes)*/ + MHD_socket bind_socket; const int max_thread_stack_size; const bool use_ssl; const bool use_ipv6; diff --git a/src/webserver.cpp b/src/webserver.cpp index 669338fa..e5122cd0 100644 --- a/src/webserver.cpp +++ b/src/webserver.cpp @@ -27,7 +27,15 @@ #include #include #include +#include + +#if defined(__MINGW32__) || defined(__CYGWIN32__) +#include +#define _WINDOWS +#else #include +#endif + #include #include #include @@ -115,12 +123,16 @@ struct compare_value } }; +#ifndef __MINGW32__ static void catcher (int sig) { } +#endif static void ignore_sigpipe () { +//Mingw doesn't implement SIGPIPE +#ifndef __MINGW32__ struct sigaction oldsig; struct sigaction sig; @@ -136,6 +148,7 @@ static void ignore_sigpipe () gettext("Failed to install SIGPIPE handler: %s\n"), strerror (errno) ); +#endif } //WEBSERVER @@ -259,7 +272,7 @@ void* webserver::select(void* self) fd_set es; struct timeval timeout_value; details::daemon_item* di = static_cast(self); - int max; + MHD_socket max; while (di->ws->is_running()) { max = 0; @@ -295,7 +308,7 @@ void* webserver::select(void* self) ++it ) { - int local_max; + MHD_socket local_max; (*it).second.supply_events(&rs, &ws, &es, &local_max); if(local_max > max) @@ -321,7 +334,9 @@ void* webserver::select(void* self) timeout_value.tv_sec = timeout_secs; timeout_value.tv_usec = timeout_microsecs; - ::select (max + 1, &rs, &ws, &es, &timeout_value); + /*On unix, MHD_socket will be an int anyway. + On windows, the cast is safe because winsock ignores first argument to select*/ + ::select ((int) max + 1, &rs, &ws, &es, &timeout_value); MHD_run (di->daemon); //EVENT SUPPLIERS DISPATCHING @@ -338,24 +353,25 @@ void* webserver::select(void* self) return 0x0; } -int create_socket (int domain, int type, int protocol) +MHD_socket create_socket (int domain, int type, int protocol) { int sock_cloexec = SOCK_CLOEXEC; int ctype = SOCK_STREAM | sock_cloexec; - int fd; - - /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo + + /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo * implementations do not set ai_socktype, e.g. RHL6.2. */ - fd = socket(domain, ctype, protocol); + MHD_socket fd = socket(domain, ctype, protocol); + +#ifdef _WINDOWS + if (fd == INVALID_SOCKET) +#else if ((fd == -1) && (errno == EINVAL || errno == EPROTONOSUPPORT) && (sock_cloexec != 0) ) +#endif { - sock_cloexec = 0; fd = socket(domain, type, protocol); } - if (-1 == fd) - return -1; return fd; } @@ -488,7 +504,7 @@ bool webserver::start(bool blocking) setsockopt (bind_socket, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof (on)); + (const char*) &on, sizeof (on)); if(use_ipv6) { @@ -496,16 +512,21 @@ bool webserver::start(bool blocking) #ifdef IPV6_V6ONLY setsockopt (bind_socket, IPPROTO_IPV6, IPV6_V6ONLY, - &on, sizeof (on) + (const char*) &on, sizeof (on) ); #endif #endif } bind(bind_socket, servaddr, addrlen); } +#ifdef _WINDOWS + unsigned long ioarg = 1; + ioctlsocket(bind_socket, FIONBIO, &ioarg); +#else int flags = fcntl (bind_socket, F_GETFL); flags |= O_NONBLOCK; fcntl (bind_socket, F_SETFL, flags); +#endif if(!bind_settled) listen(bind_socket, 1); iov.push_back(gen(MHD_OPTION_LISTEN_SOCKET, bind_socket)); @@ -730,7 +751,7 @@ int webserver::build_request_args ( mr->dhr->querystring += string(buf); } } - int size = internal_unescaper((void*) mr->ws, value); + size_t size = internal_unescaper((void*) mr->ws, value); mr->dhr->set_arg(key, string(value, size)); return MHD_YES; } @@ -1046,18 +1067,17 @@ int webserver::finalize_answer( details::http_resource_mirror >::iterator it; - int len = -1; - int tot_len = -1; + size_t len = 0; + size_t tot_len = 0; for( it=registered_resources.begin(); it!=registered_resources.end(); ++it ) { - int endpoint_pieces_len = (*it).first.get_url_pieces_num(); - int endpoint_tot_len = (*it).first.get_url_complete_size(); - if(tot_len == -1 || - len == -1 || + size_t endpoint_pieces_len = (*it).first.get_url_pieces_num(); + size_t endpoint_tot_len = (*it).first.get_url_complete_size(); + if(!found || endpoint_pieces_len > len || ( endpoint_pieces_len == len && @@ -1078,7 +1098,7 @@ int webserver::finalize_answer( { vector url_pars; - unsigned int pars_size = + size_t pars_size = found_endpoint->first.get_url_pars(url_pars); vector url_pieces;