Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ script:
./benchmark_select 8080 $(nproc) &
sleep 5 && ab -n 10000000 -c 100 localhost:8080/plaintext
fi
- |
if [ "$PERFORMANCE" = "nodelay" ]; then
cd examples
./benchmark_nodelay 8080 $(nproc) &
sleep 5 && ab -n 10000000 -c 100 localhost:8080/plaintext
fi
- |
if [ "$PERFORMANCE" = "threads" ]; then
cd examples
Expand Down Expand Up @@ -215,6 +221,16 @@ matrix:
- apache2-utils
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && PERFORMANCE=select"
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- apache2-utils
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && PERFORMANCE=nodelay"
- os: linux
addons:
apt:
Expand Down
3 changes: 2 additions & 1 deletion examples/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
LDADD = $(top_builddir)/src/libhttpserver.la
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/httpserver/
METASOURCES = AUTO
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg setting_headers custom_access_log basic_authentication digest_authentication minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads deferred_with_accumulator
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg setting_headers custom_access_log basic_authentication digest_authentication minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads benchmark_nodelay deferred_with_accumulator

hello_world_SOURCES = hello_world.cpp
service_SOURCES = service.cpp
Expand All @@ -40,3 +40,4 @@ url_registration_SOURCES = url_registration.cpp
minimal_ip_ban_SOURCES = minimal_ip_ban.cpp
benchmark_select_SOURCES = benchmark_select.cpp
benchmark_threads_SOURCES = benchmark_threads.cpp
benchmark_nodelay_SOURCES = benchmark_nodelay.cpp
41 changes: 41 additions & 0 deletions examples/benchmark_nodelay.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <httpserver.hpp>
#include <cstdlib>
#include <memory>

#define PATH "/plaintext"
#define BODY "Hello, World!"

using namespace httpserver;

class hello_world_resource : public http_resource {
public:
hello_world_resource(const std::shared_ptr<http_response>& resp):
resp(resp)
{
}

const std::shared_ptr<http_response> render(const http_request&) {
return resp;
}

private:
std::shared_ptr<http_response> resp;
};

int main(int argc, char** argv)
{
webserver ws = create_webserver(atoi(argv[1]))
.start_method(http::http_utils::INTERNAL_SELECT)
.tcp_nodelay()
.max_threads(atoi(argv[2]));

std::shared_ptr<http_response> hello = std::shared_ptr<http_response>(new string_response(BODY, 200));
hello->with_header("Server", "libhttpserver");

hello_world_resource hwr(hello);
ws.register_resource(PATH, &hwr, false);

ws.start(true);

return 0;
}
11 changes: 11 additions & 0 deletions src/httpserver/create_webserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class create_webserver
_post_process_enabled(true),
_deferred_enabled(false),
_single_resource(false),
_tcp_nodelay(false),
_not_found_resource(0x0),
_method_not_allowed_resource(0x0),
_internal_error_resource(0x0)
Expand Down Expand Up @@ -121,6 +122,7 @@ class create_webserver
_post_process_enabled(b._post_process_enabled),
_deferred_enabled(b._deferred_enabled),
_single_resource(b._single_resource),
_tcp_nodelay(b._tcp_nodelay),
_not_found_resource(b._not_found_resource),
_method_not_allowed_resource(b._method_not_allowed_resource),
_internal_error_resource(b._internal_error_resource)
Expand Down Expand Up @@ -162,6 +164,7 @@ class create_webserver
_post_process_enabled(b._post_process_enabled),
_deferred_enabled(b._deferred_enabled),
_single_resource(b._single_resource),
_tcp_nodelay(b._tcp_nodelay),
_not_found_resource(std::move(b._not_found_resource)),
_method_not_allowed_resource(std::move(b._method_not_allowed_resource)),
_internal_error_resource(std::move(b._internal_error_resource))
Expand Down Expand Up @@ -206,6 +209,7 @@ class create_webserver
this->_post_process_enabled = b._post_process_enabled;
this->_deferred_enabled = b._deferred_enabled;
this->_single_resource = b._single_resource;
this->_tcp_nodelay = b._tcp_nodelay;
this->_not_found_resource = b._not_found_resource;
this->_method_not_allowed_resource = b._method_not_allowed_resource;
this->_internal_error_resource = b._internal_error_resource;
Expand Down Expand Up @@ -251,6 +255,7 @@ class create_webserver
this->_post_process_enabled = b._post_process_enabled;
this->_deferred_enabled = b._deferred_enabled;
this->_single_resource = b._single_resource;
this->_tcp_nodelay = b._tcp_nodelay;
this->_not_found_resource = std::move(b._not_found_resource);
this->_method_not_allowed_resource = std::move(b._method_not_allowed_resource);
this->_internal_error_resource = std::move(b._internal_error_resource);
Expand Down Expand Up @@ -293,6 +298,7 @@ class create_webserver
_post_process_enabled(true),
_deferred_enabled(false),
_single_resource(false),
_tcp_nodelay(false),
_not_found_resource(0x0),
_method_not_allowed_resource(0x0),
_internal_error_resource(0x0)
Expand Down Expand Up @@ -471,6 +477,10 @@ class create_webserver
{
_single_resource = true; return *this;
}
create_webserver& tcp_nodelay()
{
_tcp_nodelay = true; return *this;
}
create_webserver& not_found_resource(render_ptr not_found_resource)
{
_not_found_resource = not_found_resource; return *this;
Expand Down Expand Up @@ -524,6 +534,7 @@ class create_webserver
bool _post_process_enabled;
bool _deferred_enabled;
bool _single_resource;
bool _tcp_nodelay;
render_ptr _not_found_resource;
render_ptr _method_not_allowed_resource;
render_ptr _internal_error_resource;
Expand Down
2 changes: 1 addition & 1 deletion src/httpserver/webserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class webserver
const bool post_process_enabled;
const bool deferred_enabled;
bool single_resource;
bool tcp_nodelay;
pthread_mutex_t mutexwait;
pthread_rwlock_t runguard;
pthread_cond_t mutexcond;
Expand All @@ -183,7 +184,6 @@ class webserver
std::map<details::http_endpoint, http_resource*> registered_resources;
std::map<std::string, http_resource*> registered_resources_str;

int next_to_choose;
std::set<http::ip_representation> bans;
std::set<http::ip_representation> allowances;

Expand Down
17 changes: 15 additions & 2 deletions src/webserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@

#if defined(__MINGW32__) || defined(__CYGWIN32__)
#include <winsock2.h>
#include <ws2tcpip.h>
#define _WINDOWS
#else
#include <netinet/ip.h>
#include <netinet/tcp.h>
#endif

#include <signal.h>
Expand Down Expand Up @@ -149,10 +151,10 @@ webserver::webserver(const create_webserver& params):
post_process_enabled(params._post_process_enabled),
deferred_enabled(params._deferred_enabled),
single_resource(params._single_resource),
tcp_nodelay(params._tcp_nodelay),
not_found_resource(params._not_found_resource),
method_not_allowed_resource(params._method_not_allowed_resource),
internal_error_resource(params._internal_error_resource),
next_to_choose(0)
internal_error_resource(params._internal_error_resource)
{
ignore_sigpipe();
pthread_mutex_init(&mutexwait, NULL);
Expand Down Expand Up @@ -758,6 +760,17 @@ int webserver::answer_to_connection(void* cls, MHD_Connection* connection,
);
}

const MHD_ConnectionInfo * conninfo = MHD_get_connection_info(
connection,
MHD_CONNECTION_INFO_CONNECTION_FD
);

if (static_cast<webserver*>(cls)->tcp_nodelay)
{
int yes = 1;
setsockopt(conninfo->connect_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &yes, sizeof(int));
}

std::string t_url = url;

base_unescaper(t_url, static_cast<webserver*>(cls)->unescaper);
Expand Down
3 changes: 2 additions & 1 deletion test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
LDADD = $(top_builddir)/src/libhttpserver.la
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/httpserver/
METASOURCES = AUTO
check_PROGRAMS = basic http_utils threaded string_utilities http_endpoint ban_system ws_start_stop authentication deferred
check_PROGRAMS = basic http_utils threaded nodelay string_utilities http_endpoint ban_system ws_start_stop authentication deferred

MOSTLYCLEANFILES = *.gcda *.gcno *.gcov

Expand All @@ -32,6 +32,7 @@ deferred_SOURCES = integ/deferred.cpp
http_utils_SOURCES = unit/http_utils_test.cpp
string_utilities_SOURCES = unit/string_utilities_test.cpp
http_endpoint_SOURCES = unit/http_endpoint_test.cpp
nodelay_SOURCES = integ/nodelay.cpp

noinst_HEADERS = littletest.hpp
AM_CXXFLAGS += -lcurl -Wall -fPIC
Expand Down
74 changes: 74 additions & 0 deletions test/integ/nodelay.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
This file is part of libhttpserver
Copyright (C) 2011-2019 Sebastiano Merlino

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/

#include "littletest.hpp"
#include <curl/curl.h>
#include <string>
#include <map>
#include "httpserver.hpp"

using namespace httpserver;
using namespace std;

class ok_resource : public http_resource
{
public:
const shared_ptr<http_response> render_GET(const http_request& req)
{
return shared_ptr<string_response>(new string_response("OK", 200, "text/plain"));
}
};

LT_BEGIN_SUITE(threaded_suite)

webserver* ws;

void set_up()
{
ws = new webserver(create_webserver(8080).tcp_nodelay());
ws->start(false);
}

void tear_down()
{
ws->stop();
delete ws;
}
LT_END_SUITE(threaded_suite)

LT_BEGIN_AUTO_TEST(threaded_suite, base)
ok_resource resource;
ws->register_resource("base", &resource);
curl_global_init(CURL_GLOBAL_ALL);
std::string s;
CURL* curl;
CURLcode res;

curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "localhost:8080/base");
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
res = curl_easy_perform(curl);
LT_ASSERT_EQ(res, 0);
curl_easy_cleanup(curl);
LT_END_AUTO_TEST(base)

LT_BEGIN_AUTO_TEST_ENV()
AUTORUN_TESTS()
LT_END_AUTO_TEST_ENV()