Skip to content

Commit 4bf9616

Browse files
committed
Adding multithreaded example from issue #3054 (by airween)
- Rewritten to use C++ libModSecurity API and std::thread (instead of pthreads)
1 parent 293cd21 commit 4bf9616

File tree

8 files changed

+144
-0
lines changed

8 files changed

+144
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ ltmain.sh
5050
examples/simple_example_using_c/test
5151
/tools/rules-check/modsec-rules-check
5252
examples/multiprocess_c/multi
53+
examples/multithread/multithread
5354
examples/reading_logs_via_rule_message/simple_request
5455
examples/reading_logs_with_offset/read
5556
examples/using_bodies_in_chunks/simple_request

build/win32/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ setExampleTargetProperties(reading_logs_via_rule_message)
259259
add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc)
260260
setExampleTargetProperties(reading_logs_with_offset)
261261

262+
# multithread
263+
add_executable(multithread ${BASE_DIR}/examples/multithread/multithread.cc)
264+
setExampleTargetProperties(multithread)
265+
262266
# tools
263267
#
264268

build/win32/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Built files will be located in the directory: `build\win32\build\[build_configur
5151
* `using_bodies_in_chunks.exe`
5252
* `reading_logs_via_rule_message.exe`
5353
* `reading_logs_with_offset.exe`
54+
* `multithread.exe`
5455
* Executable files for tools
5556
* `rules_check.exe`
5657

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ AM_COND_IF([EXAMPLES],
423423
examples/Makefile \
424424
examples/simple_example_using_c/Makefile \
425425
examples/multiprocess_c/Makefile \
426+
examples/multithread/Makefile \
426427
examples/reading_logs_with_offset/Makefile \
427428
examples/reading_logs_via_rule_message/Makefile \
428429
examples/using_bodies_in_chunks/Makefile \

examples/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I build
44

55
SUBDIRS = \
66
multiprocess_c \
7+
multithread \
78
reading_logs_with_offset \
89
reading_logs_via_rule_message \
910
simple_example_using_c \

examples/multithread/Makefile.am

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
3+
noinst_PROGRAMS = multithread
4+
5+
multithread_SOURCES = \
6+
multithread.cc
7+
8+
multithread_LDADD = \
9+
$(CURL_LDADD) \
10+
$(GEOIP_LDADD) \
11+
$(GLOBAL_LDADD) \
12+
$(LIBXML2_LDADD) \
13+
$(LMDB_LDADD) \
14+
$(MAXMIND_LDADD) \
15+
$(LUA_LDADD) \
16+
$(PCRE_LDADD) \
17+
$(SSDEEP_LDADD) \
18+
$(YAJL_LDADD)
19+
20+
multithread_LDFLAGS = \
21+
-L$(top_builddir)/src/.libs/ \
22+
$(GEOIP_LDFLAGS) \
23+
-lmodsecurity \
24+
-lm \
25+
-lstdc++ \
26+
$(LMDB_LDFLAGS) \
27+
$(LUA_LDFLAGS) \
28+
$(MAXMIND_LDFLAGS) \
29+
$(SSDEEP_LDFLAGS) \
30+
$(YAJL_LDFLAGS)
31+
32+
multithread_CPPFLAGS = \
33+
$(GLOBAL_CFLAGS) \
34+
-I$(top_builddir)/headers \
35+
-I$(top_builddir) \
36+
-g \
37+
-I../others \
38+
-fPIC \
39+
-O3 \
40+
$(CURL_CFLAGS) \
41+
$(GEOIP_CFLAGS) \
42+
$(GLOBAL_CPPFLAGS) \
43+
$(MODSEC_NO_LOGS) \
44+
$(YAJL_CFLAGS) \
45+
$(LMDB_CFLAGS) \
46+
$(LUA_CFLAGS) \
47+
$(PCRE_CFLAGS) \
48+
$(LIBXML2_CFLAGS)
49+
50+
51+
MAINTAINERCLEANFILES = \
52+
Makefile.in
53+
54+

examples/multithread/basic_rules.conf

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
SecDebugLog debug.log
2+
SecDebugLogLevel 9
3+
4+
5+
SecRule REQUEST_HEADERS:User-Agent ".*" "id:1,phase:1,t:sha1,t:hexEncode,setvar:tx.ua_hash=%{MATCHED_VAR}"
6+
7+
SecAction "id:2,phase:2,initcol:ip=%{REMOTE_ADDR}_%{tx.ua_hash}"
8+
9+
SecRule REQUEST_HEADERS:User-Agent "@rx .*" "id:3,phase:2,setvar:ip.auth_attempt=+1"
10+
11+
SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar,expirevar:ip.foo=2"
12+
#SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar"
13+
SecRule IP "@rx bar" "id:5,phase:2,pass"
14+
SecRule IP:auth_attempt "@rx bar" "id:6,phase:2,pass"

examples/multithread/multithread.cc

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <iostream>
2+
#include <thread>
3+
#include <array>
4+
5+
#include <modsecurity/modsecurity.h>
6+
#include <modsecurity/transaction.h>
7+
#include <modsecurity/rules_set.h>
8+
9+
static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules, int tid) {
10+
std::cout << "Hello World! It's me, thread #" << tid << std::endl;
11+
12+
for(int i = 0; i != 1'000; i++) {
13+
auto modsecTransaction = std::make_unique<modsecurity::Transaction>(modsec, rules, nullptr);
14+
15+
modsecTransaction->processConnection("127.0.0.1", 12345, "127.0.0.1", 80);
16+
modsecTransaction->processURI(
17+
"https://www.modsecurity.org/test?foo=herewego",
18+
"GET", "1.1");
19+
20+
modsecTransaction->addRequestHeader("User-Agent",
21+
"Basic ModSecurity example");
22+
modsecTransaction->processRequestHeaders();
23+
modsecTransaction->processRequestBody();
24+
25+
modsecTransaction->addResponseHeader("HTTP/1.1",
26+
"200 OK");
27+
modsecTransaction->processResponseHeaders(200, "HTTP 1.2");
28+
modsecTransaction->processResponseBody();
29+
30+
modsecTransaction->processLogging();
31+
32+
std::this_thread::sleep_for(std::chrono::microseconds(100));
33+
}
34+
35+
std::cout << "Thread #" << tid << " exits" << std::endl;
36+
}
37+
38+
int main (int argc, char *argv[]) {
39+
auto modsec = std::make_unique<modsecurity::ModSecurity>();
40+
modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha (Simple " \
41+
"example on how to use ModSecurity API");
42+
43+
char main_rule_uri[] = "basic_rules.conf";
44+
auto rules = std::make_unique<modsecurity::RulesSet>();
45+
if (rules->loadFromUri(main_rule_uri) < 0) {
46+
std::cerr << "Problems loading the rules..." << std::endl;
47+
std::cerr << rules->m_parserError.str() << std::endl;
48+
return -1;
49+
}
50+
51+
constexpr auto NUM_THREADS = 100;
52+
std::array<std::thread, NUM_THREADS> threads;
53+
54+
for (auto i = 0; i != threads.size(); ++i) {
55+
threads[i] = std::thread(
56+
[&modsec, &rules, i]() {
57+
process_request(modsec.get(), rules.get(), i);
58+
});
59+
}
60+
61+
std::this_thread::sleep_for(std::chrono::microseconds(10000));
62+
63+
for (auto i = 0; i != threads.size(); ++i) {
64+
threads[i].join();
65+
}
66+
67+
return 0;
68+
}

0 commit comments

Comments
 (0)