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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,13 @@ else()
message(STATUS "FLB Event loop backend > auto discovery (Monkey library)")
endif()

# Monkey uses its bundled libevent backend on Windows. Link it statically so
# Fluent Bit binaries do not require event.dll at runtime.
if(FLB_SYSTEM_WINDOWS)
set(EVENT__LIBRARY_TYPE STATIC CACHE STRING
"Build Monkey's bundled libevent as a static library" FORCE)
endif()

# Build Monkey HTTP Server
if(FLB_HTTP_SERVER)
add_subdirectory(${FLB_PATH_LIB_MONKEY} EXCLUDE_FROM_ALL)
Expand Down
81 changes: 80 additions & 1 deletion lib/monkey/.github/workflows/build-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ jobs:
arch: x64
cmake_additional_opt: ""
os: windows-latest
cmake_version: "3.31.6"
- name: "Windows 64bit (ARM)"
arch: amd64_arm64
cmake_additional_opt: "-G \"NMake Makefiles\" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION=10.0 -DCMAKE_SYSTEM_PROCESSOR=ARM64"
cmake_additional_opt: "-G \"NMake Makefiles\" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_VERSION=10.0 -DCMAKE_SYSTEM_PROCESSOR=ARM64 -DMK_TLS_BACKEND=mbedtls"
os: windows-latest
cmake_version: "3.31.6"
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -35,6 +37,83 @@ jobs:
with:
arch: ${{ matrix.config.arch }}

- name: Set up CMake
run: |
$cmakeVersion = "${{ matrix.config.cmake_version }}"
$cmakeArch = "x86_64"
$cmakeUrl = "https://github.com/Kitware/CMake/releases/download/v${cmakeVersion}/cmake-${cmakeVersion}-windows-${cmakeArch}.zip"
$cmakeZip = "$env:RUNNER_TEMP\cmake-${cmakeVersion}.zip"
$cmakeDir = "C:\Program Files\CMake"

Write-Host "Downloading CMake ${cmakeVersion} from official GitHub releases: ${cmakeUrl}"

# Download with retry logic
$maxRetries = 3
$retryCount = 0
$downloaded = $false

while ($retryCount -lt $maxRetries -and -not $downloaded) {
try {
$retryCount++
Write-Host "Attempt $retryCount of $maxRetries"
Invoke-WebRequest -Uri $cmakeUrl -OutFile $cmakeZip -UseBasicParsing -ErrorAction Stop

# Verify file was downloaded and has content
if (Test-Path $cmakeZip) {
$fileInfo = Get-Item $cmakeZip
if ($fileInfo.Length -gt 0) {
Write-Host "Download successful. File size: $($fileInfo.Length) bytes"
$downloaded = $true
} else {
Write-Host "Downloaded file is empty, retrying..."
Remove-Item $cmakeZip -Force -ErrorAction SilentlyContinue
}
}
} catch {
Write-Host "Download attempt $retryCount failed: $_"
if ($retryCount -lt $maxRetries) {
Start-Sleep -Seconds 2
Remove-Item $cmakeZip -Force -ErrorAction SilentlyContinue
} else {
throw "Failed to download CMake after $maxRetries attempts: $_"
}
}
}

# Verify it's a valid ZIP file by checking the header (ZIP files start with PK)
$header = [System.IO.File]::ReadAllBytes($cmakeZip)[0..1]
if (-not ($header[0] -eq 0x50 -and $header[1] -eq 0x4B)) {
Write-Host "Warning: File may not be a valid ZIP. First bytes: $($header[0]), $($header[1])"
Write-Host "Expected: 80, 75 (PK in hex)"
throw "Downloaded file is not a valid ZIP archive"
}
Write-Host "ZIP file validation passed (PK header found)"

Write-Host "Extracting CMake to C:\Program Files"
# Remove existing CMake directory if it exists
if (Test-Path $cmakeDir) {
Remove-Item $cmakeDir -Recurse -Force
}

# Extract ZIP file
Expand-Archive -Path $cmakeZip -DestinationPath "C:\Program Files" -Force

# Rename extracted folder to standard CMake directory name
$extractedDir = "C:\Program Files\cmake-${cmakeVersion}-windows-${cmakeArch}"
if (Test-Path $extractedDir) {
Rename-Item -Path $extractedDir -NewName "CMake" -Force
}

# Verify installation
$cmakeExe = "$cmakeDir\bin\cmake.exe"
if (Test-Path $cmakeExe) {
Write-Host "CMake installed successfully"
& $cmakeExe --version
} else {
throw "CMake installation verification failed: $cmakeExe not found"
}
shell: pwsh

- name: Build on ${{ matrix.os }} with vs-2019
run: |
mkdir build
Expand Down
1 change: 1 addition & 0 deletions lib/monkey/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ lib/python/conf/*
lib/python/jemalloc.config
src/include/
build/
integration_tests/.venv/
include/monkey/mk_static_plugins.h
include/monkey/mk_core/mk_core_info.h
.vscode
Expand Down
184 changes: 184 additions & 0 deletions lib/monkey/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# AGENTS

This file is the local operating guide for agents working in this repository.
It focuses on two things:

- how the Monkey source tree is organized
- how commits are written in the existing Git history

## Repository map

Monkey is a small HTTP server written in C. The tree is split by subsystem.

- `mk_core/`
Core utilities used by the server and plugins.
Includes memory helpers, strings, files, thread helpers, event loops,
I/O vectors, config parsing, and generic utilities.

- `mk_server/`
The HTTP server implementation.
This is where connection handling, request parsing, header generation,
virtual hosts, MIME resolution, scheduler integration, streams, plugins,
and server lifecycle live.

- `mk_bin/`
The standalone `monkey` executable entrypoints and signal handling.

- `include/monkey/`
Public and internal headers for the core, server, parser, plugins,
config, events, streams, and API types.

- `plugins/`
Optional server features.
Examples in this tree include `liana`, `mandril`, `dirlisting`, `cgi`,
`fastcgi`, `auth`, `logger`, `tls`, and `cheetah`.

- `api/`
Small API-focused programs and tests.

- `test/`
Native unit/integration-style test targets used by CMake.

- `fuzz/`
Fuzzing entrypoints and helpers for parser and request handling.

- `conf/`
Config templates installed or copied at build/install time.

- `htdocs/`
Default static site content used by the standalone server.

- `cmake/`
CMake helper modules and build logic.

- `deps/`
Bundled third-party dependencies such as regex, rbtree, libco,
and mbedtls sources.

- `qa/`
Extra request fixtures and local QA artifacts.

## Main runtime flow

When debugging behavior, the usual path is:

1. `mk_bin/monkey.c`
Starts the binary.
2. `mk_server/monkey.c`, `mk_server/mk_server.c`
Initializes the server and worker threads.
3. `mk_server/mk_scheduler.c`
Drives socket events into protocol handlers.
4. `mk_server/mk_http.c`
Owns HTTP session lifecycle, request preparation, response handling,
range parsing, file serving, keepalive, and teardown.
5. `mk_server/mk_http_parser.c`
Parses the request line, headers, body state, and chunked transfer coding.
6. `mk_server/mk_header.c`, `mk_server/mk_stream.c`
Build and send responses.

Useful supporting code:

- `mk_server/mk_vhost.c`
Virtual host lookup, per-vhost file descriptor table.
- `mk_server/mk_mimetype.c`
File extension to MIME mapping.
- `mk_server/mk_user.c`
`~user` URI handling.
- `mk_server/mk_plugin.c`
Plugin registration and API exposure.
- `mk_core/mk_event_*.c`
Backend-specific event loop implementations.

## Build and verification

Typical local build entrypoint:

```bash
cmake --build build
```

If a fresh build tree is needed, inspect `CMakeLists.txt` and the generated
`build/` layout before changing build flags. The project currently requires
CMake 3.20 and produces `build/bin/monkey`.

## Commit style used in this repository

Follow the existing Git history, not the older wording in `CONTRIBUTING.md`.

### Subject format

Use a short, lowercase, scope-prefixed subject. The common patterns are:

- `build: bump to v1.8.7`
- `server: clean thread destroy on worker loop exit`
- `server: http: move initialization of request headers to request init`
- `core: event: Plug descriptor leaks in an error case.`
- `parser: fixed header loss issue caused by duplicated headers`
- `logger: set log file permissions to 0600, closes CVE-2013-1771 (#413)`

### Prefix rules

Pick the narrowest stable prefix that matches the area being changed.

- `build:` for version bumps, CMake, workflows, packaging
- `core:` for `mk_core/` functionality
- `server:` for `mk_server/` functionality
- `server: http:` for `mk_server/mk_http.c` and closely related request flow
- `server: parser:` or `server: http_parser:` for parser-specific work
- `plugin:` or a plugin-specific prefix when the change is isolated there
- `test:` for tests
- `logger:`, `scheduler:`, `mimetype:`, `config:` when the change is clearly
isolated to that subsystem and history already uses that style
- backend-specific prefixes like `mk_event_kqueue:` are acceptable when the
change is narrow and entirely local to that backend

### Subject style rules

- keep it concise
- prefer lowercase after the prefix
- use colon-separated scopes, not bracket tags
- do not invent long marketing titles
- keep the subject under 80 characters
- match existing nouns already used in history where possible

Good examples for this tree:

- `server: http: reject malformed range delimiters`
- `server: http: avoid reusing invalid request state`
- `server: parser: validate chunk length tokens strictly`
- `core: memory: handle null mk_ptr_to_buf input`

Bad examples for this tree:

- `Fix CVEs`
- `Monkey: important security fixes`
- `HTTP: Add Various Improvements`
- `misc: cleanup`

## Commit body rules

The older contribution guide still applies well here.

- include a body for non-trivial changes
- wrap body lines at about 80 columns
- explain the bug, the fix, and any verification done
- if the change is security-related, describe the faulty path precisely
- if multiple root causes exist, prefer separate commits

When I am asked to commit in this repository, default behavior should be:

1. split unrelated changes into separate commits
2. choose the narrowest prefix from the existing history
3. write a short lowercase subject
4. add a body for anything beyond trivial cleanup
5. use `git commit -s` unless the user explicitly asks otherwise

## Working rules for this repository

- Do not touch unrelated untracked files in the worktree.
- Be careful around parser and request lifecycle code. Many bugs surface later
in teardown, not at the first invalid input.
- Prefer minimal targeted fixes over broad refactors unless requested.
- When a bug crosses files, still group the commit by root cause, not by file.
- For security fixes, verify behavior on the built binary, not only by code
inspection.
40 changes: 31 additions & 9 deletions lib/monkey/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ endif()
# Monkey Version
set(MK_VERSION_MAJOR 1)
set(MK_VERSION_MINOR 8)
set(MK_VERSION_PATCH 7)
set(MK_VERSION_PATCH 9)
set(MK_VERSION_STR "${MK_VERSION_MAJOR}.${MK_VERSION_MINOR}.${MK_VERSION_PATCH}")

# Output paths
Expand Down Expand Up @@ -59,10 +59,15 @@ option(MK_PLUGIN_CGI "CGI support" No)
option(MK_PLUGIN_CHEETAH "Cheetah Shell Interface" No)
option(MK_PLUGIN_DIRLISTING "Directory Listing" Yes)
option(MK_PLUGIN_FASTCGI "FastCGI" No)
option(MK_PLUGIN_LIANA "Basic network layer" Yes)
option(MK_PLUGIN_LOGGER "Log Writer" No)
option(MK_PLUGIN_MANDRIL "Security" Yes)
option(MK_PLUGIN_TLS "TLS/SSL support" No)
option(MK_TLS "TLS/SSL support" Yes)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Tie Monkey TLS to FLB_TLS

When Fluent Bit is configured with -DFLB_TLS=Off while the HTTP server remains enabled, this independent default still leaves MK_TLS=ON; the Monkey subdirectory then discovers OpenSSL or builds its bundled mbedTLS backend. TLS-disabled Fluent Bit builds therefore retain TLS dependencies and code instead of honoring the top-level option, so this setting should inherit FLB_TLS when Monkey is embedded.

Useful? React with 👍 / 👎.

set(MK_TLS_BACKEND "auto" CACHE STRING "TLS backend: auto, openssl, or mbedtls")
set_property(CACHE MK_TLS_BACKEND PROPERTY STRINGS auto openssl mbedtls)

if(DEFINED MK_PLUGIN_TLS)
set(MK_TLS ${MK_PLUGIN_TLS})
endif()

# Options to build Monkey with/without binary and
# static/dynamic library modes (default is always just
Expand Down Expand Up @@ -101,12 +106,6 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(MK_SYSTEM_MALLOC 1)
endif()

if(MK_STATIC_PLUGINS)
set(MK_STATIC_PLUGINS "${MK_STATIC_PLUGINS},liana")
else()
set(MK_STATIC_PLUGINS "liana")
endif()

# Variable to be populated by plugins/CMakeLists.txt. It will contain the
# code required to initialize any static plugin.
set(STATIC_PLUGINS_INIT "")
Expand All @@ -133,6 +132,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
MK_DEFINITION(_CRT_SECURE_NO_WARNINGS)
endif()

if (MK_TLS)
MK_DEFINITION(MK_HAVE_TLS)
endif()

# Enable experimental (dev) HTTP/2 support
if (MK_HTTP2)
MK_DEFINITION(MK_HAVE_HTTP2)
Expand Down Expand Up @@ -233,6 +236,23 @@ endif()
# =========== CONFIGURATION FILES=============
# ============================================

# Build/runtime paths
#
# These defaults make an in-tree build immediately runnable via ./bin/monkey
# while still allowing packagers to override them with cache entries.
set(MK_PATH_CONF "${PROJECT_BINARY_DIR}/conf" CACHE PATH
"Default Monkey configuration directory")
set(MK_PATH_LOG "${PROJECT_BINARY_DIR}/logs" CACHE PATH
"Default Monkey log directory")
set(MK_PATH_PIDPATH "${PROJECT_BINARY_DIR}/run" CACHE PATH
"Default Monkey PID directory")
set(MK_PATH_WWW "${PROJECT_SOURCE_DIR}/htdocs" CACHE PATH
"Default Monkey document root")

file(MAKE_DIRECTORY "${MK_PATH_CONF}")
file(MAKE_DIRECTORY "${MK_PATH_LOG}")
file(MAKE_DIRECTORY "${MK_PATH_PIDPATH}")

# Default values for conf/monkey.conf
set(MK_CONF_LISTEN "2001")
set(MK_CONF_WORKERS "0")
Expand All @@ -251,6 +271,7 @@ set(MK_CONF_SYMLINK "Off")
set(MK_CONF_DEFAULT_MIME "text/plain")
set(MK_CONF_FDT "On")
set(MK_CONF_OVERCAPACITY "Resist")
set(MK_PIDFILE "${MK_CONF_PIDFILE}")

# Default values for conf/sites/default
set(MK_VH_SERVERNAME "127.0.0.1")
Expand Down Expand Up @@ -318,6 +339,7 @@ add_subdirectory(deps/rbtree)
add_subdirectory(deps/regex)
add_subdirectory(deps/flb_libco)
add_subdirectory(mk_core)
add_subdirectory(tls)
add_subdirectory(plugins)
add_subdirectory(mk_server)

Expand Down
Loading
Loading