From 8ae5cddb9b6e9ed1acf3c3f3f0bab31d29a03972 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Tue, 29 Jan 2019 12:06:58 -0500 Subject: [PATCH 01/10] better get0_notBefore ssl defs --- sslutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sslutils.c b/sslutils.c index 9f724d6..87568c6 100644 --- a/sslutils.c +++ b/sslutils.c @@ -11,8 +11,8 @@ #include "internal.h" #if OPENSSL_VERSION_NUMBER < 0x10100000L -#define X509_get0_notBefore X509_get_notBefore -#define X509_get0_notAfter X509_get_notAfter +#define X509_get0_notBefore(x) X509_get_notBefore(x) +#define X509_get0_notAfter(x) X509_get_notAfter(x) #endif unsigned char * From 718c406fd206aa4ca37f3c67f1b3a52702928bbb Mon Sep 17 00:00:00 2001 From: Nathan French Date: Tue, 29 Jan 2019 19:19:11 -0500 Subject: [PATCH 02/10] update test_client with new addr --- examples/test_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test_client.c b/examples/test_client.c index 8a5983c..aa5ac4c 100644 --- a/examples/test_client.c +++ b/examples/test_client.c @@ -52,7 +52,7 @@ main(int argc, char ** argv) evhtp_request_t * request; evbase = event_base_new(); - conn = evhtp_connection_new(evbase, "75.126.169.52", 80); + conn = evhtp_connection_new(evbase, "104.27.150.225", 80); request = evhtp_request_new(request_cb, evbase); evhtp_request_set_hook(request, evhtp_hook_on_read, print_data, evbase); From 874a225ddcec9a514e782539e4df3c36d5fea82f Mon Sep 17 00:00:00 2001 From: Nathan French Date: Tue, 29 Jan 2019 19:35:29 -0500 Subject: [PATCH 03/10] cleanup / optimization for iovec operations --- evhtp.c | 70 +++++++++++++++------------------------------------------ 1 file changed, 18 insertions(+), 52 deletions(-) diff --git a/evhtp.c b/evhtp.c index ca76c98..8d34676 100644 --- a/evhtp.c +++ b/evhtp.c @@ -2044,20 +2044,13 @@ htp__evbuffer_add_iovec_(struct evbuffer * buf, struct evbuffer_iovec * vec, int static int htp__create_headers_(evhtp_header_t * header, void * arg) { - struct evbuffer * buf = arg; - struct evbuffer_iovec iov[4]; - - iov[0].iov_base = header->key; - iov[0].iov_len = header->klen; - - iov[1].iov_base = ": "; - iov[1].iov_len = 2; - - iov[2].iov_base = header->val; - iov[2].iov_len = header->vlen; - - iov[3].iov_base = "\r\n"; - iov[3].iov_len = 2; + struct evbuffer * buf = arg; + struct evbuffer_iovec iov[4] = { + { header->key, header->klen }, + { ": ", 2 }, + { header->val, header->vlen }, + { "\r\n", 2 } + }; htp__evbuffer_add_iovec_(buf, iov, 4); @@ -2168,45 +2161,18 @@ htp__create_reply_(evhtp_request_t * request, evhtp_res code) * of the header. */ { - struct evbuffer_iovec iov[9]; const char * status_str = status_code_to_str(code); - - /* data == "HTTP/" */ - iov[0].iov_base = "HTTP/"; - iov[0].iov_len = 5; - - /* data == "HTTP/X" */ - iov[1].iov_base = (void *)&major; - iov[1].iov_len = 1; - - /* data == "HTTP/X." */ - iov[2].iov_base = "."; - iov[2].iov_len = 1; - - /* data == "HTTP/X.X" */ - iov[3].iov_base = (void *)&minor; - iov[3].iov_len = 1; - - - /* data == "HTTP/X.X " */ - iov[4].iov_base = " "; - iov[4].iov_len = 1; - - /* data == "HTTP/X.X YYY" */ - iov[5].iov_base = out_buf; - iov[5].iov_len = strlen(out_buf); - - /* data == "HTTP/X.X YYY " */ - iov[6].iov_base = " "; - iov[6].iov_len = 1; - - /* data == "HTTP/X.X YYY ZZZ" */ - iov[7].iov_base = (void *)status_str; - iov[7].iov_len = strlen(status_str); - - /* data == "HTTP/X.X YYY ZZZ\r\n" */ - iov[8].iov_base = "\r\n"; - iov[8].iov_len = 2; + struct evbuffer_iovec iov[9] = { + { "HTTP/1", 5 }, /* data == "HTTP/" */ + { (void *)&major, 1 }, /* data == "HTTP/X */ + { ".", 1 }, /* data == "HTTP/X." */ + { (void *)&minor, 1 }, /* data == "HTTP/X.X" */ + { " ", 1 }, /* data == "HTTP/X.X " */ + { out_buf, strlen(out_buf) }, /* data = "HTTP/X.X YYY" */ + { " ", 1 }, /* data = "HTTP/X.X YYY " */ + { (void *)status_str, strlen(status_str) }, /* data = "HTTP/X.X YYY ZZZ" */ + { "\r\n", 2 }, /* data = "HTTP/X.X YYY ZZZ\r\n" */ + }; htp__evbuffer_add_iovec_(buf, iov, 9); } From 01ad044edf966a3a3a29d744024c8b3b7b0d5ae6 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Wed, 6 Feb 2019 11:46:03 -0500 Subject: [PATCH 04/10] Release v1.2.18, see ChangeLog for details --- CMakeLists.txt | 2 +- ChangeLog | 12 +++++++++++- include/evhtp/evhtp.h | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f625af..481ddd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -project(libevhtp VERSION "1.2.17") +project(libevhtp VERSION "1.2.18") # For us YCM users. set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/ChangeLog b/ChangeLog index 2a4491e..7b4d906 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ -v1.2.17 +v1.2.18 + o Add htp__evbuffer_add_iovec_ helper for libevent < 2.1 (8991567 Nathan French) + o [#122] Fix compilation without deprecated OpenSSL 1.1 APIs (78e8e41 Rosen Penev) + o [#122] Reorganize OpenSSL < 1.0.0 compatibility for greater readability. (8e543fe Rosen Penev) + o [#123] add missing include for ssize_t (6a74ec7 maxice8) + o [#123] include sys/types only if EVHTP_HAS_SYS_TYPES is set (0839f8e Nathan French) + o [#122] cleanup for ssl locking changes (7d0fd5d Nathan French) + o better get0_notBefore ssl defs (8ae5cdd Nathan French) + o cleanup / optimization for iovec operations (874a225 Nathan French) + +v1.2.17 (alpha/beta) o [#111] assert frontends not compiled with -DNDEBUG (07d6f5f Nathan French) o [#111] Remove asserts for alloc functions. (#112) (114bf53 Nathan French) o [#108] do not include content-length with chunked (#113) (73255df Nathan French) diff --git a/include/evhtp/evhtp.h b/include/evhtp/evhtp.h index 33372fe..9bcee44 100644 --- a/include/evhtp/evhtp.h +++ b/include/evhtp/evhtp.h @@ -189,10 +189,10 @@ typedef evhtp_ssl_sess_t * (* evhtp_ssl_scache_get)(evhtp_connection_t * connect typedef void * (* evhtp_ssl_scache_init)(evhtp_t *); #endif -#define EVHTP_VERSION "1.2.17" +#define EVHTP_VERSION "1.2.18" #define EVHTP_VERSION_MAJOR 1 #define EVHTP_VERSION_MINOR 2 -#define EVHTP_VERSION_PATCH 17 +#define EVHTP_VERSION_PATCH 18 #define evhtp_headers_iterator evhtp_kvs_iterator From 3294cf469fa2700b349f7621e6a6823d106825de Mon Sep 17 00:00:00 2001 From: Nathan French Date: Wed, 6 Feb 2019 21:52:33 -0500 Subject: [PATCH 05/10] update readme / iovec optimizations --- README.markdown | 135 ------------------------------ README.md | 49 +++++++++++ evhtp.c | 32 +++++--- examples/CMakeLists.txt | 11 ++- examples/reuse_thread_svr.c | 158 ++++++++++++++++++++++++++++++++++++ parser.c | 2 +- 6 files changed, 237 insertions(+), 150 deletions(-) delete mode 100644 README.markdown create mode 100644 README.md create mode 100644 examples/reuse_thread_svr.c diff --git a/README.markdown b/README.markdown deleted file mode 100644 index 6acebd5..0000000 --- a/README.markdown +++ /dev/null @@ -1,135 +0,0 @@ -| ![LOGO](http://i.imgur.com/uBd4iIz.png) |

Libevhtp

| -| :------------- | -------------: | - -[![Build Status](https://travis-ci.org/criticalstack/libevhtp.svg?branch=develop)](https://travis-ci.org/criticalstack/libevhtp) -[![Gitter](https://badges.gitter.im/criticalstack/libevhtp.svg)](https://gitter.im/criticalstack/libevhtp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - - Coverity Scan Build Status - - -This document describes details on using the evhtp API. This document is -probably not very awesome, it's best to look at test.c to see advanced usage. - -# Prebuilt Packages -[![Package Versions](https://repology.org/badge/vertical-allrepos/libevhtp.svg)](https://repology.org/metapackage/libevhtp) - -## Required Dependencies -* [gcc](http://gcc.gnu.org/) -* [Libevent2](http://libevent.org) - -## Optional Dependencies -* [OpenSSL](http://openssl.org) -* pthreads -* [onig (regex)](https://github.com/kkos/oniguruma) - -## Building -* cd build -* cmake .. -* make -* make examples - -## Overview -*** - -Libevhtp was created as a replacement API for Libevent's current HTTP API. The reality of libevent's http interface is that it was created as a JIT server, meaning the developer never thought of it being used for creating a full-fledged HTTP service. Infact I am under the impression that the libevent http API was designed almost as an example of what you can do with libevent. It's not Apache in a box, but more and more developers are attempting to use it as so. - -### Libevent's HTTP pitfalls -*** - -* It was not designed to be a fully functional HTTP server. -* The code is messy, abstractions are almost non-existent, and feature-creep has made long-term maintainability very hard. -* The parsing code is slow and requires data to be buffered before a full parse can be completed. This results in extranious memory usage and lots of string comparison functions. -* There is no method for a user to access various parts of the request processing cycle. For example if the "Content-Length" header has a value of 50000, your callback is not executed until all 50000 bytes have been read. -* Setting callback URI's do exact matches; meaning if you set a callback for "/foo/", requests for "/foo/bar/" are ignored. -* Creating an HTTPS server is hard, it requires a bunch of work to be done on the underlying bufferevents. -* As far as I know, streaming data back to a client is hard, if not impossible without messing with underlying bufferevents. -* It's confusing to work with, this is probably due to the lack of proper documentation. - -Libevhtp attempts to address these problems along with a wide variety of cool mechanisms allowing a developer to have complete control over your server operations. This is not to say the API cannot be used in a very simplistic manner - a developer can easily create a backwards compatible version of libevent's HTTP server to libevhtp. - -### A bit about the architecture of libevhtp -*** - -#### Bootstrapping - -1. Create a parent evhtp_t structure. -2. Assign callbacks to the parent for specific URIs or posix-regex based URI's -3. Optionally assign per-connection hooks (see hooks) to the callbacks. -4. Optionally assign pre-accept and post-accept callbacks for incoming connections. -5. Optionally enable built-in threadpool for connection handling (lock-free, and non-blocking). -6. Optionally morph your server to HTTPS. -7. Start the evhtp listener. - -#### Request handling. - -1. Optionally deal with pre-accept and post-accept callbacks if they exist, allowing for a connection to be rejected if the function deems it as unacceptable. -2. Optionally assign per-request hooks (see hooks) for a request (the most optimal place for setting these hooks is on a post-accept callback). -3. Deal with either per-connection or per-request hook callbacks if they exist. -4. Once the request has been fully processed, inform evhtp to send a reply. - -##### A very basic example with no optional conditions. - - #include - #include - - void - testcb(evhtp_request_t * req, void * a) { - evbuffer_add_reference(req->buffer_out, "foobar", 6, NULL, NULL); - evhtp_send_reply(req, EVHTP_RES_OK); - } - - int - main(int argc, char ** argv) { - evbase_t * evbase = event_base_new(); - evhtp_t * htp = evhtp_new(evbase, NULL); - - evhtp_set_cb(htp, "/test", testcb, NULL); - evhtp_bind_socket(htp, "0.0.0.0", 8080, 1024); - event_base_loop(evbase, 0); - return 0; - } - - -## Is evhtp thread-safe? - -For simple usage with evhtp_use_threads(), yes. But for more extreme cases: -sorta, you are bound to the thread mechanisms of libevent itself. - -But with proper design around libevhtp, thread issues can be out-of-sight, -out-of-mind. - -What do you mean by this "proper design" statement? - -Refer to the code in ./examples/thread_design.c. The comments go into great detail -of the hows and whys for proper design using libevhtp's threading model. - -This example uses redis, mainly because most people who have asked me "is evhtp -thread-safe" were attempting to *other things* before sending a response to a -request. And on more than one occasion, those *other things* were communicating -with redis. - - -## For Windows MinGW - - cmake -G "MSYS Makefiles" -DCMAKE_INCLUDE_PATH=/mingw/include -DCMAKE_LIBRARY_PATH=/mingw/lib -DCMAKE_INSTALL_PREFIX=/mingw . - - make - -## Performance stuff - -While we never documented any benchmark publically, -the popular open source project [ZIMG](http://zimg.buaa.us) did a bit of that -for us.The ZIMG team decided to move away from NGINX to libevhtp for their -software, and the results were pretty outstanding. Here is a graph showing their -application under very high load - -![ZIMG GRAPH](/zimg_vs_nginx.png) - -The X-axis is the number of connections, while the Y-axis is requests per -second. - -You can read the whole article here: [Architecture Design of an Image Server](http://zimg.buaa.us/documents/Architecture_Design_of_Image_Server/) - -Slightly outdated (Now faster!) -![HI NGINX](http://i.imgur.com/kiSkSLH.png) diff --git a/README.md b/README.md new file mode 100644 index 0000000..11b1ac0 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +| ![LOGO](http://i.imgur.com/uBd4iIz.png) |

Libevhtp

| +| :------------- | -------------: | + +[![Build Status](https://travis-ci.org/criticalstack/libevhtp.svg?branch=develop)](https://travis-ci.org/criticalstack/libevhtp) +[![Gitter](https://badges.gitter.im/criticalstack/libevhtp.svg)](https://gitter.im/criticalstack/libevhtp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Packaging status](https://repology.org/badge/tiny-repos/libevhtp.svg)](https://repology.org/metapackage/libevhtp/versions) + + + Coverity Scan Build Status + + +## Required Dependencies +* [gcc](http://gcc.gnu.org/) or [clang](https://clang.llvm.org/) +* [Libevent2](http://libevent.org) +* [CMake](http://cmake.org) + +## Optional Dependencies +* [OpenSSL](http://openssl.org) +* pthreads +* [onig (regex)](https://github.com/kkos/oniguruma) + +## Building +* cd build +* cmake .. +* make +* make examples + +## For Windows MinGW +* cmake -G "MSYS Makefiles" -DCMAKE_INCLUDE_PATH=/mingw/include -DCMAKE_LIBRARY_PATH=/mingw/lib -DCMAKE_INSTALL_PREFIX=/mingw . +* make + +## Performance stuff + +While we never documented any benchmark publically, +the popular open source project [ZIMG](http://zimg.buaa.us) did a bit of that +for us.The ZIMG team decided to move away from NGINX to libevhtp for their +software, and the results were pretty outstanding. Here is a graph showing their +application under very high load + +![ZIMG GRAPH](/zimg_vs_nginx.png) + +The X-axis is the number of connections, while the Y-axis is requests per +second. + +You can read the whole article here: [Architecture Design of an Image Server](http://zimg.buaa.us/documents/Architecture_Design_of_Image_Server/) + +Slightly outdated (Now faster!) +![HI NGINX](http://i.imgur.com/kiSkSLH.png) diff --git a/evhtp.c b/evhtp.c index 8d34676..63fdf18 100644 --- a/evhtp.c +++ b/evhtp.c @@ -4,6 +4,7 @@ * @brief implementation file for libevhtp. */ +#define _GNU_SOURCE #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include /* MIN/MAX macro */ #ifndef WIN32 #include #include @@ -2013,32 +2015,38 @@ htp__request_parse_fini_(htparser * p) return 0; } /* htp__request_parse_fini_ */ -static size_t +static int htp__evbuffer_add_iovec_(struct evbuffer * buf, struct evbuffer_iovec * vec, int n_vec) { -#if LIBEVENT_VERSION_NUMBER < 0x02010000 int n; - size_t res; size_t to_alloc; + char * bufptr; + size_t to_copy; - res = to_alloc = 0; + to_alloc = 0; for (n = 0; n < n_vec; n++) { to_alloc += vec[n].iov_len; } - evbuffer_expand(buf, to_alloc); + char buffer[to_alloc]; - for (n = 0; n < n_vec; n++) { - evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len); + bufptr = buffer; + to_copy = to_alloc; + + for (n = 0; n < n_vec; n++) + { + size_t copy = MIN(vec[n].iov_len, to_copy); + + bufptr = mempcpy(bufptr, vec[n].iov_base, copy); + to_copy -= copy; - res += vec[n].iov_len; + if (evhtp_unlikely(to_copy == 0)) { + break; + } } - return res; -#else - return evbuffer_add_iovec(buf, vec, n_vec); -#endif + return evbuffer_add(buf, buffer, to_alloc); } static int diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4723214..c53a116 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -13,8 +13,15 @@ add_executable(example_request_fini EXCLUDE_FROM_ALL example_request_fini.c) add_executable(example_basic EXCLUDE_FROM_ALL example_basic.c) if(NOT EVHTP_DISABLE_EVTHR) - #add_executable(example_locality EXCLUDE_FROM_ALL example_locality.c) - #target_link_libraries(example_locality evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS}) + if ("${CMAKE_SYSTEM}" MATCHES "Linux") + add_executable(example_locality EXCLUDE_FROM_ALL example_locality.c) + target_link_libraries(example_locality evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS}) + + add_executable(reuse_thread_svr EXCLUDE_FROM_ALL reuse_thread_svr.c) + target_link_libraries(reuse_thread_svr evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS}) + + add_dependencies(examples example_locality reuse_thread_svr) + endif() add_executable(test_proxy EXCLUDE_FROM_ALL test_proxy.c) target_link_libraries(test_proxy evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS}) diff --git a/examples/reuse_thread_svr.c b/examples/reuse_thread_svr.c new file mode 100644 index 0000000..96bc80a --- /dev/null +++ b/examples/reuse_thread_svr.c @@ -0,0 +1,158 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define CPU__COUNT sysconf(_SC_NPROCESSORS_ONLN) + +static int _init = 0; +static int _threads = 0; + +#define _valid_response(REQ, TYPE) \ + (REQ)->method == htp_method_ ## TYPE ? \ + EVHTP_RES_OK : EVHTP_RES_400 + +static void +on_request_index(evhtp_request_t * req, void * _) +{ + return evhtp_send_reply(req, _valid_response(req, GET)); +} + +static void +on_request_user_register(evhtp_request_t * req, void * _) +{ + return evhtp_send_reply(req, _valid_response(req, POST)); +} + +#define upm_start uri->path->match_start +#define upm_eoff uri->path->matched_eoff +#define upm_soff uri->path->matched_soff + +static void +on_request_user_index(evhtp_request_t * req, void * _) +{ + if (req->method == htp_method_GET) { + evbuffer_add_reference(req->buffer_out, + req->upm_start, + req->upm_eoff - req->upm_soff, NULL, NULL); + + return evhtp_send_reply(req, EVHTP_RES_OK); + } + + return evhtp_send_reply(req, EVHTP_RES_400); +} + +static void +dummy_eventcb_(int sock, short which, void * args) +{ + (void)sock; + (void)which; + (void)args; +} + +static void +attach_cbpf_(int fd) +{ + struct sock_filter code[] = { + { BPF_LD | BPF_W | BPF_ABS, 0, 0, + (__u32)(SKF_AD_OFF + SKF_AD_CPU) }, /* A = raw_smp_processor_id() */ + { BPF_RET | BPF_A, 0, 0,0}, /* return A */ + }; + + struct sock_fprog p = { + .len = 2, + .filter = code, + }; + + if (setsockopt(fd, SOL_SOCKET, + SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)) == -1) { + fprintf(stderr, "%s\n", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static void +htp_worker_init_(evthr_t * thread, void * args) +{ + struct event_base * evbase; + struct evhtp * htp; + int core; + cpu_set_t cpu_set; + + if (!(evbase = evthr_get_base(thread))) { + evthr_stop(thread); + return; + } + + if (!(htp = evhtp_new(evbase, thread))) { + evthr_stop(thread); + return; + } + + evhtp_set_regex_cb(htp, "^/user/([^/]+)", on_request_user_index, NULL); + evhtp_set_cb(htp, "/user", on_request_user_register, NULL); + evhtp_set_cb(htp, "/", on_request_index, NULL); + + core = _threads++ % CPU__COUNT; + + CPU_ZERO(&cpu_set); + CPU_SET(core, &cpu_set); + + pthread_setaffinity_np(pthread_self(), + sizeof(cpu_set_t), &cpu_set); + +#if 0 + if (pthread_getaffinity_np(pthread_self(), + sizeof(cpu_set_t), &cpu_set) == 0) { + int i; + + for (i = 0; i < CPU__COUNT; i++) { + if (CPU_ISSET(i, &cpu_set)) { + } + } + } +#endif + + evhtp_enable_flag(htp, EVHTP_FLAG_ENABLE_ALL); + evhtp_bind_socket(htp, "0.0.0.0", 3000, 1024); + + attach_cbpf_(evconnlistener_get_fd(htp->server)); +} /* htp_worker_init_ */ + +int +main(int argc, char ** argv) +{ + struct event_base * evbase; + struct event * dummy_ev; + evthr_pool_t * workers; + + evbase = event_base_new(); + dummy_ev = event_new(evbase, -1, EV_READ | EV_PERSIST, + dummy_eventcb_, NULL); + + event_add(dummy_ev, NULL); + + if (!(workers = evthr_pool_wexit_new(CPU__COUNT, + htp_worker_init_, NULL, NULL))) { + exit(EXIT_FAILURE); + } + + evthr_pool_start(workers); + event_base_loop(evbase, 0); + + return 0; +} diff --git a/parser.c b/parser.c index 2bb84a1..efe8ec4 100644 --- a/parser.c +++ b/parser.c @@ -569,7 +569,7 @@ void htparser_init(htparser * p, htp_type type) { /* Do not memset entire string buffer. */ - memset(p, 0, offsetof(htparser, buf)); + //memset(p, 0, offsetof(htparser, buf)); p->buf[0] = '\0'; p->state = s_start; p->error = htparse_error_none; From 9488ad5e133b3959525b7535f86892590e3cbe56 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Thu, 7 Feb 2019 00:07:49 -0500 Subject: [PATCH 06/10] only inlcude linux/filter for cbpf ops --- examples/reuse_thread_svr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/reuse_thread_svr.c b/examples/reuse_thread_svr.c index 96bc80a..06dc366 100644 --- a/examples/reuse_thread_svr.c +++ b/examples/reuse_thread_svr.c @@ -11,7 +11,6 @@ #include #include -#include #include #include From cdf1b96378d1b8651e16bbecc27e2a1c8249ea46 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Thu, 7 Feb 2019 08:27:27 -0500 Subject: [PATCH 07/10] only inlcude linux/filter for cbpf ops in locality too --- examples/example_locality.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/example_locality.c b/examples/example_locality.c index 3a292db..c744650 100644 --- a/examples/example_locality.c +++ b/examples/example_locality.c @@ -11,7 +11,6 @@ #include #include -#include #include #include From 3ab8322b6d5b826ffc9838a7300d5499876df817 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Thu, 7 Feb 2019 08:34:21 -0500 Subject: [PATCH 08/10] check for SO_ATTACH_REUSEPORT_CBPF decl --- examples/example_locality.c | 4 ++++ examples/reuse_thread_svr.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/examples/example_locality.c b/examples/example_locality.c index c744650..328aec4 100644 --- a/examples/example_locality.c +++ b/examples/example_locality.c @@ -16,6 +16,10 @@ #include #include +#ifndef SO_ATTACH_REUSEPORT_CBPF +#define SO_ATTACH_REUSEPORT_CBPF 51 +#endif + #define CPU__COUNT sysconf(_SC_NPROCESSORS_ONLN) static int _init = 0; diff --git a/examples/reuse_thread_svr.c b/examples/reuse_thread_svr.c index 06dc366..4adc2c3 100644 --- a/examples/reuse_thread_svr.c +++ b/examples/reuse_thread_svr.c @@ -16,6 +16,10 @@ #include #include +#ifndef SO_ATTACH_REUSEPORT_CBPF +#define SO_ATTACH_REUSEPORT_CBPF 51 +#endif + #define CPU__COUNT sysconf(_SC_NPROCESSORS_ONLN) static int _init = 0; From f4907eeae18db899fdb52be2609ca33722f437e8 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Fri, 8 Mar 2019 09:37:13 -0500 Subject: [PATCH 09/10] [#128] fix parser bug which skipped bytes in long uris --- parser.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/parser.c b/parser.c index efe8ec4..07f0f76 100644 --- a/parser.c +++ b/parser.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -1234,6 +1235,10 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) break; } + if (evhtp_unlikely(i + 1 >= len)) { + break; + } + ch = data[++i]; } while (i < len); From 00ccb5c80f7cfc3405ec39ce105f0f63a7425151 Mon Sep 17 00:00:00 2001 From: Nathan French Date: Sat, 9 Mar 2019 15:19:23 -0500 Subject: [PATCH 10/10] [#128] fix other (potential) problems related #128 --- parser.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/parser.c b/parser.c index 07f0f76..9587455 100644 --- a/parser.c +++ b/parser.c @@ -835,6 +835,10 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) HTP_SET_BUF(ch); } + if (evhtp_unlikely(i + 1 >= len)) { + break; + } + ch = data[++i]; } while (i < len); @@ -1319,6 +1323,10 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) break; } + if (evhtp_unlikely(i + 1 >= len)) { + break; + } + ch = data[++i]; } while (i < len); @@ -1734,6 +1742,10 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len) break; } + if (evhtp_unlikely(i + 1 >= len)) { + break; + } + ch = data[++i]; } while (i < len);