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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
*.o
serve
serve_*
serve.gcno
logs/log_*.txt
*.info
report
logs
report
blacklist.txt
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.PHONY: all report cppcheck gcc-analyzer clang-tidy

all: serve_debug serve_cov serve

serve_debug: serve.c
Expand All @@ -13,3 +15,13 @@ report:
lcov --capture --directory . --output-file coverage.info
@ mkdir -p report
genhtml coverage.info --output-directory report

cppcheck:
cppcheck -j1 --enable=portability serve.c
cppcheck -j1 --enable=style serve.c

gcc-analyzer:
gcc -c -fanalyzer serve.c

clang-tidy:
clang-tidy serve.c
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@
This is a minimal web server designed to serve my blog. I'm writing it to be robust enough to face the public internet. You can see it in action at http://playin.coz.is/index.html. You probably can't get it to crash, but feel free to try! And if you manage to do it, send me an email to show off! I'll leave the coolest attempts in `attempts.txt`.

# Specs
- Linux only
- HTTP/1.1 + pipelining + keep-alive
- Request and connection deadlines
- Only runs on Linux
- HTTP/1.1 support with pipelining and keep-alive
- Uses request and connection timeouts
- IP blacklist
- Access log, log file rotation, hard disk usage limits
- No `Transfer-Encoding: Chunked` (when receiving a chunked request the server responds with `411 Length Required`, prompting the client to try again with the `Content-Length` header)
- Static file serving utilities
- Single core (This will probably change when I get a better VPS)

# How I test it
I'm still testing manually. I usually stress test the server locally using `wrk` and see if it breaks. I also test it under `valgrind` and sanitizers.
# Testing
I routinely run the server under valgrind or sanitizers (address, undefined) and target it using `wrk`. I'm also adding automatized tests to `tests/test.py` to check compliance with the HTTP/1.1 spec.

# Blocking IPs
To block any number of IP addresses you need to create a `blacklist.txt` file and insert the IPs. You can also add comments:
```
# I'm a comment
10.0.0.1
127.0.0.1 # I'm a comment too
```
Blocked addresses will be rejected after being accepted. This is just a best effort solution as you should block connections using iptables or nftables.

# Known Issues
- Server replies to HTTP/1.0 clients as HTTP/1.1
- Since poll is edge triggered, when the server is full and can't accept all new connections the remaining ones are left waiting until some other event wakes up poll()
Loading