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
42 changes: 4 additions & 38 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,14 @@ jobs:
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
strategy:
matrix:
select_impl: ['select', 'poll']
steps:
- name: checkout
uses: actions/checkout@v4
- name: install libraries
run: sudo apt-get update && sudo apt-get install -y libbrotli-dev libcurl4-openssl-dev
- name: build and run tests
env:
SELECT_IMPL: ${{ matrix.select_impl }}
run: cd test && make
- name: run fuzz test target
env:
SELECT_IMPL: ${{ matrix.select_impl }}
run: cd test && make fuzz_test

macos:
Expand All @@ -67,19 +60,12 @@ jobs:
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
strategy:
matrix:
select_impl: ['select', 'poll']
steps:
- name: checkout
uses: actions/checkout@v4
- name: build and run tests
env:
SELECT_IMPL: ${{ matrix.select_impl }}
run: cd test && make
- name: run fuzz test target
env:
SELECT_IMPL: ${{ matrix.select_impl }}
run: cd test && make fuzz_test

windows:
Expand All @@ -89,9 +75,6 @@ jobs:
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true')
strategy:
matrix:
select_impl: ['select', 'poll']
steps:
- name: Prepare Git for Checkout on Windows
run: |
Expand All @@ -113,33 +96,16 @@ jobs:
choco install openssl

- name: Configure CMake with SSL
run: >
cmake -B build -S .
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
-DHTTPLIB_TEST=ON
-DHTTPLIB_REQUIRE_OPENSSL=ON
-DHTTPLIB_REQUIRE_ZLIB=ON
-DHTTPLIB_REQUIRE_BROTLI=ON
-DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }}
run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DHTTPLIB_TEST=ON -DHTTPLIB_REQUIRE_OPENSSL=ON -DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_BROTLI=ON
- name: Build with with SSL
run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine /nologo
run: cmake --build build --config Release
- name: Run tests with SSL
run: ctest --output-on-failure --test-dir build -C Release

- name: Configure CMake without SSL
run: >
cmake -B build-no-ssl -S .
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DHTTPLIB_TEST=ON
-DHTTPLIB_REQUIRE_OPENSSL=OFF
-DHTTPLIB_REQUIRE_ZLIB=ON
-DHTTPLIB_REQUIRE_BROTLI=ON
-DHTTPLIB_USE_SELECT=${{ matrix.select_impl == 'select' && 'ON' || 'OFF' }}
run: cmake -B build-no-ssl -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DHTTPLIB_TEST=ON -DHTTPLIB_REQUIRE_OPENSSL=OFF -DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_BROTLI=ON
- name: Build without SSL
run: cmake --build build-no-ssl --config Release -- /v:m /clp:ShowCommandLine /nologo
run: cmake --build build-no-ssl --config Release
- name: Run tests without SSL
run: ctest --output-on-failure --test-dir build-no-ssl -C Release
env:
Expand Down
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* HTTPLIB_REQUIRE_ZLIB (default off)
* HTTPLIB_REQUIRE_BROTLI (default off)
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
* HTTPLIB_USE_SELECT (default off) choose between select() and poll()
* HTTPLIB_COMPILE (default off)
* HTTPLIB_INSTALL (default on)
* HTTPLIB_TEST (default off)
Expand Down Expand Up @@ -47,7 +46,6 @@
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
* HTTPLIB_IS_USING_SELECT - a bool for if select() is used instead of poll().
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
Expand Down Expand Up @@ -103,7 +101,6 @@ option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
option(HTTPLIB_USE_SELECT "Uses select() instead of poll()." OFF)
# Defaults to static library
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
Expand All @@ -115,7 +112,6 @@ endif()
# Set some variables that are used in-tree and while building based on our options
set(HTTPLIB_IS_COMPILED ${HTTPLIB_COMPILE})
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN ${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN})
set(HTTPLIB_IS_USING_SELECT ${HTTPLIB_USE_SELECT})

# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
Expand Down Expand Up @@ -242,7 +238,6 @@ target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
$<$<BOOL:${HTTPLIB_IS_USING_SELECT}>:CPPHTTPLIB_USE_SELECT>
)

# CMake configuration files installation directory
Expand Down
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -872,11 +872,6 @@ res->body; // Compressed data

```

Use `select()` instead of `poll()`
----------------------------------

cpp-httplib defaults to the widely supported `poll()` system call. If your OS lacks support for `poll()`, define `CPPHTTPLIB_USE_SELECT` to use `select()` instead.

Unix Domain Socket Support
--------------------------

Expand Down
84 changes: 2 additions & 82 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,6 @@
#define CPPHTTPLIB_LISTEN_BACKLOG 5
#endif

#if !defined(CPPHTTPLIB_USE_POLL) && !defined(CPPHTTPLIB_USE_SELECT)
#define CPPHTTPLIB_USE_POLL
#elif defined(CPPHTTPLIB_USE_POLL) && defined(CPPHTTPLIB_USE_SELECT)
#error "CPPHTTPLIB_USE_POLL and CPPHTTPLIB_USE_SELECT are mutually exclusive"
#endif

/*
* Headers
*/
Expand Down Expand Up @@ -200,9 +194,7 @@ using ssize_t = long;

using socket_t = SOCKET;
using socklen_t = int;
#ifdef CPPHTTPLIB_USE_POLL
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
#endif

#else // not _WIN32

Expand All @@ -222,16 +214,11 @@ using socklen_t = int;
#ifdef __linux__
#include <resolv.h>
#endif
#include <csignal>
#include <netinet/tcp.h>
#ifdef CPPHTTPLIB_USE_POLL
#include <poll.h>
#endif
#include <csignal>
#include <pthread.h>
#include <sys/mman.h>
#ifndef __VMS
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
Expand Down Expand Up @@ -3265,33 +3252,13 @@ inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size,

template <bool Read>
inline ssize_t select_impl(socket_t sock, time_t sec, time_t usec) {
#ifdef CPPHTTPLIB_USE_POLL
struct pollfd pfd;
pfd.fd = sock;
pfd.events = (Read ? POLLIN : POLLOUT);

auto timeout = static_cast<int>(sec * 1000 + usec / 1000);

return handle_EINTR([&]() { return poll(&pfd, 1, timeout); });
#else
#ifndef _WIN32
if (sock >= FD_SETSIZE) { return -1; }
#endif

fd_set fds, *rfds, *wfds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
rfds = (Read ? &fds : nullptr);
wfds = (Read ? nullptr : &fds);

timeval tv;
tv.tv_sec = static_cast<long>(sec);
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);

return handle_EINTR([&]() {
return select(static_cast<int>(sock + 1), rfds, wfds, nullptr, &tv);
});
#endif
}

inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) {
Expand All @@ -3304,7 +3271,6 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {

inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
time_t usec) {
#ifdef CPPHTTPLIB_USE_POLL
struct pollfd pfd_read;
pfd_read.fd = sock;
pfd_read.events = POLLIN | POLLOUT;
Expand All @@ -3325,38 +3291,6 @@ inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
}

return Error::Connection;
#else
#ifndef _WIN32
if (sock >= FD_SETSIZE) { return Error::Connection; }
#endif

fd_set fdsr;
FD_ZERO(&fdsr);
FD_SET(sock, &fdsr);

auto fdsw = fdsr;
auto fdse = fdsr;

timeval tv;
tv.tv_sec = static_cast<long>(sec);
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);

auto ret = handle_EINTR([&]() {
return select(static_cast<int>(sock + 1), &fdsr, &fdsw, &fdse, &tv);
});

if (ret == 0) { return Error::ConnectionTimeout; }

if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) {
auto error = 0;
socklen_t len = sizeof(error);
auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char *>(&error), &len);
auto successful = res >= 0 && !error;
return successful ? Error::Success : Error::Connection;
}
return Error::Connection;
#endif
}

inline bool is_socket_alive(socket_t sock) {
Expand Down Expand Up @@ -7202,20 +7136,6 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
res.version = "HTTP/1.1";
res.headers = default_headers_;

#ifdef _WIN32
// TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL).
#else
#ifndef CPPHTTPLIB_USE_POLL
// Socket file descriptor exceeded FD_SETSIZE...
if (strm.socket() >= FD_SETSIZE) {
Headers dummy;
detail::read_headers(strm, dummy);
res.status = StatusCode::InternalServerError_500;
return write_response(strm, close_connection, req, res);
}
#endif
#endif

// Request line and headers
if (!parse_request_line(line_reader.ptr(), req) ||
!detail::read_headers(strm, req.headers)) {
Expand Down Expand Up @@ -10446,7 +10366,7 @@ inline SSL_CTX *Client::ssl_context() const {

} // namespace httplib

#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL)
#ifdef _WIN32
#undef poll
#endif

Expand Down
11 changes: 1 addition & 10 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,17 @@ project(
meson_version: '>=0.62.0'
)

cxx = meson.get_compiler('cpp')

# Check just in case downstream decides to edit the source
# and add a project version
version = meson.project_version()
if version == 'undefined'
cxx = meson.get_compiler('cpp')
version = cxx.get_define('CPPHTTPLIB_VERSION',
prefix: '#include <httplib.h>',
include_directories: include_directories('.')).strip('"')
assert(version != '', 'failed to get version from httplib.h')
endif

if cxx.has_function('poll', prefix: '#include <poll.h>')
# Use poll if present
add_project_arguments('-DCPPHTTPLIB_USE_POLL', language: 'cpp')
elif cxx.has_function('select', prefix: '#include <sys/select.h>')
# Use select otherwise
add_project_arguments('-DCPPHTTPLIB_USE_SELECT', language: 'cpp')
endif

deps = [dependency('threads')]
args = []

Expand Down
4 changes: 0 additions & 4 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
CXX = clang++
CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS -fsanitize=address

ifeq ($(SELECT_IMPL),select)
CXXFLAGS += -DCPPHTTPLIB_USE_SELECT
endif

PREFIX ?= $(shell brew --prefix)

OPENSSL_DIR = $(PREFIX)/opt/openssl@3
Expand Down
Loading