@velox0/cerver 0.6.2-nightly.20260531.8 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Makefile +21 -2
- package/WINDOWS.md +6 -12
- package/lib/commands/build.js +1 -1
- package/lib/compiler/compile.js +2 -41
- package/package.json +1 -1
- package/runtime/cerver.h +16 -17
- package/runtime/fetch.c +22 -5
- package/runtime/http_parser.c +4 -0
- package/runtime/http_writer.c +2 -0
- package/runtime/mime.c +4 -0
- package/runtime/router.c +3 -0
- package/runtime/server.c +207 -177
- package/runtime/tests/runtime_tests.c +77 -38
- package/runtime/win_compat.h +272 -18
package/Makefile
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
CC ?= cc
|
|
2
|
-
CFLAGS ?= -std=c11 -Wall -Wextra -O2
|
|
2
|
+
CFLAGS ?= -std=c11 -Wall -Wextra -O2
|
|
3
|
+
WIN_CC ?= x86_64-w64-mingw32-gcc
|
|
4
|
+
WIN_CFLAGS ?= -std=c11 -Wall -Wextra -O2 -D_WIN32_WINNT=0x0601 -DWIN32_LEAN_AND_MEAN -DCERVER_NO_CURL
|
|
5
|
+
WIN_LDFLAGS ?= -lws2_32 -lmswsock -ladvapi32
|
|
3
6
|
|
|
4
7
|
RUNTIME_SRCS = \
|
|
5
8
|
runtime/http_parser.c \
|
|
@@ -13,8 +16,14 @@ RUNTIME_SRCS = \
|
|
|
13
16
|
TEST_SRCS = runtime/tests/runtime_tests.c \
|
|
14
17
|
runtime/tests/minunit.c
|
|
15
18
|
TEST_BIN = build/runtime_tests
|
|
19
|
+
WIN_TEST_BIN = build/runtime_tests.exe
|
|
20
|
+
WIN_OBJ = build/server.win.o
|
|
16
21
|
|
|
17
|
-
.PHONY: test-runtime clean
|
|
22
|
+
.PHONY: test tests test-runtime test-windows clean
|
|
23
|
+
|
|
24
|
+
test: test-runtime test-windows
|
|
25
|
+
|
|
26
|
+
tests: test
|
|
18
27
|
|
|
19
28
|
test-runtime: $(TEST_BIN)
|
|
20
29
|
./$(TEST_BIN)
|
|
@@ -23,5 +32,15 @@ $(TEST_BIN): $(RUNTIME_SRCS) $(TEST_SRCS) runtime/cerver.h
|
|
|
23
32
|
mkdir -p build
|
|
24
33
|
$(CC) $(CFLAGS) -Iruntime -o $(TEST_BIN) $(RUNTIME_SRCS) $(TEST_SRCS) -pthread -lcurl
|
|
25
34
|
|
|
35
|
+
test-windows: $(WIN_TEST_BIN) $(WIN_OBJ)
|
|
36
|
+
|
|
37
|
+
$(WIN_TEST_BIN): $(RUNTIME_SRCS) $(TEST_SRCS) runtime/cerver.h
|
|
38
|
+
mkdir -p build
|
|
39
|
+
$(WIN_CC) $(WIN_CFLAGS) -Iruntime -o $(WIN_TEST_BIN) $(RUNTIME_SRCS) $(TEST_SRCS) $(WIN_LDFLAGS)
|
|
40
|
+
|
|
41
|
+
$(WIN_OBJ): runtime/server.c runtime/cerver.h
|
|
42
|
+
mkdir -p build
|
|
43
|
+
$(WIN_CC) $(WIN_CFLAGS) -Iruntime -c runtime/server.c -o $(WIN_OBJ)
|
|
44
|
+
|
|
26
45
|
clean:
|
|
27
46
|
rm -rf build
|
package/WINDOWS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Cerver on Windows
|
|
2
2
|
|
|
3
|
-
Cerver compiles your routes to native C and links against
|
|
4
|
-
On Windows you need a C toolchain that
|
|
3
|
+
Cerver compiles your routes to native C and links against Winsock2 and (optionally) libcurl.
|
|
4
|
+
On Windows you need a C toolchain that can build a console executable. Two easy options:
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ On Windows you need a C toolchain that provides these. Two easy options:
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
# MinGW-w64 (recommended for standalone .exe)
|
|
16
|
-
pacman -S mingw-w64-x86_64-gcc
|
|
16
|
+
pacman -S mingw-w64-x86_64-gcc
|
|
17
17
|
|
|
18
18
|
# If you want fetch() support (outbound HTTP):
|
|
19
19
|
pacman -S mingw-w64-x86_64-curl
|
|
@@ -28,17 +28,11 @@ On Windows you need a C toolchain that provides these. Two easy options:
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Option B — LLVM/Clang for Windows
|
|
31
|
+
## Option B — LLVM/Clang for Windows
|
|
32
32
|
|
|
33
33
|
1. Install Clang from https://releases.llvm.org/ (choose the Windows installer).
|
|
34
34
|
|
|
35
|
-
2.
|
|
36
|
-
(or clone + build from https://github.com/jwinarske/pthreads4w).
|
|
37
|
-
|
|
38
|
-
3. Place the pthreads4w headers and `.a` / `.lib` somewhere on your PATH / in a standard
|
|
39
|
-
location (e.g. `C:\pthreads4w`). Cerver's compiler probe will find them automatically.
|
|
40
|
-
|
|
41
|
-
4. If you want `fetch()` support, install libcurl for Windows from https://curl.se/windows/
|
|
35
|
+
2. If you want `fetch()` support, install libcurl for Windows from https://curl.se/windows/
|
|
42
36
|
and add it to PATH / link path.
|
|
43
37
|
|
|
44
38
|
---
|
|
@@ -61,7 +55,7 @@ The `build` command produces `dist\server.exe`. The `run` command executes it d
|
|
|
61
55
|
| Symptom | Fix |
|
|
62
56
|
|---|---|
|
|
63
57
|
| `no C compiler found` | Add `gcc` or `clang` to `PATH`; see Option A/B above |
|
|
64
|
-
|
|
|
58
|
+
| thread runtime compiler errors | Make sure you are using the bundled runtime headers from the same Cerver version |
|
|
65
59
|
| `undefined reference to curl_*` | Install libcurl and ensure `libcurl.a` / `libcurl.dll.a` are findable |
|
|
66
60
|
| `WSAStartup failed` | Should not happen; report a bug |
|
|
67
61
|
| `cerver build` passes but binary crashes | Run from the project root, not from `dist\` |
|
package/lib/commands/build.js
CHANGED
|
@@ -155,7 +155,7 @@ async function build(opts) {
|
|
|
155
155
|
/* ---- 7. Compile ---- */
|
|
156
156
|
console.log(" → compiling...");
|
|
157
157
|
if (process.platform === "win32") {
|
|
158
|
-
console.log(" Windows target — ensure gcc/clang
|
|
158
|
+
console.log(" Windows target — ensure gcc/clang is on PATH");
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/* Detect if any route uses fetch() — only link libcurl when needed */
|
package/lib/compiler/compile.js
CHANGED
|
@@ -61,38 +61,6 @@ function supportsFlag(cc, flag) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/* ------------------------------------------------------------------ */
|
|
65
|
-
/* Windows: locate pthreads-win32 / pthreads4w */
|
|
66
|
-
/* ------------------------------------------------------------------ */
|
|
67
|
-
|
|
68
|
-
function findPthreadsWin(cc) {
|
|
69
|
-
// Try common install locations for pthreads-win32/pthreads4w.
|
|
70
|
-
// MSYS2/MinGW installs it to the mingw64 tree; standalone
|
|
71
|
-
// pthreads4w may be in C:\pthreads4w or C:\pthreads-win32.
|
|
72
|
-
const candidates = [
|
|
73
|
-
// MSYS2 MinGW-w64
|
|
74
|
-
"C:\\msys64\\mingw64",
|
|
75
|
-
"C:\\msys64\\ucrt64",
|
|
76
|
-
"C:\\msys2\\mingw64",
|
|
77
|
-
// WinLibs / standalone
|
|
78
|
-
"C:\\mingw64",
|
|
79
|
-
"C:\\mingw-w64",
|
|
80
|
-
// pthreads4w default install
|
|
81
|
-
"C:\\pthreads4w",
|
|
82
|
-
"C:\\pthreads-win32",
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
for (const base of candidates) {
|
|
86
|
-
const inc = path.join(base, "include");
|
|
87
|
-
const lib = path.join(base, "lib");
|
|
88
|
-
const h = path.join(inc, "pthread.h");
|
|
89
|
-
// Accept if header exists
|
|
90
|
-
if (fs.existsSync(h)) return { inc, lib };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return null; // caller will warn and continue without explicit -I/-L
|
|
94
|
-
}
|
|
95
|
-
|
|
96
64
|
/* ------------------------------------------------------------------ */
|
|
97
65
|
/* Main compile function */
|
|
98
66
|
/* ------------------------------------------------------------------ */
|
|
@@ -158,13 +126,6 @@ function compile(distDir, runtimeDir, opts) {
|
|
|
158
126
|
/* Windows: link Winsock2, ws2_32 required for socket API */
|
|
159
127
|
args.push("-lws2_32");
|
|
160
128
|
|
|
161
|
-
/* pthreads — try to point the compiler at a local install */
|
|
162
|
-
const pt = findPthreadsWin(cc);
|
|
163
|
-
if (pt) {
|
|
164
|
-
args.push(`-I${pt.inc}`, `-L${pt.lib}`);
|
|
165
|
-
}
|
|
166
|
-
args.push("-lpthread");
|
|
167
|
-
|
|
168
129
|
/* libcurl for fetch() */
|
|
169
130
|
if (opts && opts.usesFetch) {
|
|
170
131
|
args.push("-lcurl");
|
|
@@ -177,7 +138,7 @@ function compile(distDir, runtimeDir, opts) {
|
|
|
177
138
|
/* Produce a console binary (not a GUI window) */
|
|
178
139
|
args.push("-mconsole");
|
|
179
140
|
} else {
|
|
180
|
-
/* POSIX:
|
|
141
|
+
/* POSIX: thread support + optional libcurl */
|
|
181
142
|
args.push("-lpthread");
|
|
182
143
|
if (opts && opts.usesFetch) {
|
|
183
144
|
args.push("-lcurl");
|
|
@@ -234,7 +195,7 @@ function compile(distDir, runtimeDir, opts) {
|
|
|
234
195
|
throw new Error(
|
|
235
196
|
`cerver: compilation failed (exit code ${err.status})\n` +
|
|
236
197
|
(IS_WINDOWS
|
|
237
|
-
? " Tip: ensure gcc/clang
|
|
198
|
+
? " Tip: ensure gcc/clang and (if using fetch) libcurl are installed."
|
|
238
199
|
: "")
|
|
239
200
|
);
|
|
240
201
|
}
|
package/package.json
CHANGED
package/runtime/cerver.h
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
#include <stddef.h>
|
|
15
15
|
#include <stdint.h>
|
|
16
|
-
#include <pthread.h>
|
|
17
16
|
|
|
18
17
|
/* ------------------------------------------------------------------ */
|
|
19
18
|
/* Limits */
|
|
@@ -36,9 +35,9 @@
|
|
|
36
35
|
#define CERVER_MAX_EVENTS 256
|
|
37
36
|
#define CERVER_LISTEN_BACKLOG 4096
|
|
38
37
|
|
|
39
|
-
/*
|
|
40
|
-
#define
|
|
41
|
-
#define CERVER_TASK_QUEUE_SIZE
|
|
38
|
+
/* Connection worker architecture */
|
|
39
|
+
#define CERVER_CONNECTION_WORKER_DEFAULT 4
|
|
40
|
+
#define CERVER_TASK_QUEUE_SIZE 1024
|
|
42
41
|
|
|
43
42
|
/* Stat cache for filesystem serving */
|
|
44
43
|
#define CERVER_STAT_CACHE_SIZE 256
|
|
@@ -180,7 +179,7 @@ typedef struct {
|
|
|
180
179
|
|
|
181
180
|
typedef struct {
|
|
182
181
|
cerver_stat_entry_t entries[CERVER_STAT_CACHE_SIZE];
|
|
183
|
-
|
|
182
|
+
cerver_mutex_t lock;
|
|
184
183
|
} cerver_stat_cache_t;
|
|
185
184
|
|
|
186
185
|
/* ------------------------------------------------------------------ */
|
|
@@ -190,18 +189,18 @@ typedef struct {
|
|
|
190
189
|
typedef cerver_handler_fn (*cerver_dispatch_fn)(cerver_request_t* req);
|
|
191
190
|
|
|
192
191
|
/* ------------------------------------------------------------------ */
|
|
193
|
-
/*
|
|
192
|
+
/* Acceptor state (per-core event loop) */
|
|
194
193
|
/* ------------------------------------------------------------------ */
|
|
195
194
|
|
|
196
195
|
typedef struct cerver_server cerver_server_t;
|
|
197
196
|
|
|
198
197
|
typedef struct {
|
|
199
|
-
int
|
|
200
|
-
int
|
|
201
|
-
|
|
202
|
-
cerver_server_t*
|
|
203
|
-
|
|
204
|
-
}
|
|
198
|
+
int id;
|
|
199
|
+
int event_fd; /* kqueue or epoll fd */
|
|
200
|
+
cerver_sock_t listen_fd; /* per-acceptor on Linux, shared on macOS */
|
|
201
|
+
cerver_server_t* srv;
|
|
202
|
+
cerver_acceptor_thread_t thread;
|
|
203
|
+
} cerver_acceptor_t;
|
|
205
204
|
|
|
206
205
|
/* ------------------------------------------------------------------ */
|
|
207
206
|
/* Server */
|
|
@@ -209,7 +208,7 @@ typedef struct {
|
|
|
209
208
|
|
|
210
209
|
struct cerver_server {
|
|
211
210
|
int port;
|
|
212
|
-
|
|
211
|
+
cerver_sock_t sock_fd;
|
|
213
212
|
cerver_route_t* routes;
|
|
214
213
|
int route_count;
|
|
215
214
|
cerver_asset_t* assets;
|
|
@@ -223,10 +222,10 @@ struct cerver_server {
|
|
|
223
222
|
/* Stat cache for filesystem serving */
|
|
224
223
|
cerver_stat_cache_t stat_cache;
|
|
225
224
|
|
|
226
|
-
/*
|
|
227
|
-
int
|
|
228
|
-
int
|
|
229
|
-
|
|
225
|
+
/* Connection worker pool */
|
|
226
|
+
int connection_worker_count; /* configured connection worker count */
|
|
227
|
+
int acceptor_count; /* actual acceptor thread count */
|
|
228
|
+
cerver_acceptor_t* acceptors;
|
|
230
229
|
|
|
231
230
|
/* Route trie for radix/trie-based routing */
|
|
232
231
|
void* route_trie;
|
package/runtime/fetch.c
CHANGED
|
@@ -10,10 +10,25 @@
|
|
|
10
10
|
|
|
11
11
|
#include "cerver.h"
|
|
12
12
|
|
|
13
|
-
#include <
|
|
13
|
+
#include <stdio.h>
|
|
14
14
|
#include <stdlib.h>
|
|
15
15
|
#include <string.h>
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
#if defined(CERVER_NO_CURL)
|
|
18
|
+
char* cerver_fetch(const char* url, const char* method, const char* body, const char** headers) {
|
|
19
|
+
(void)url;
|
|
20
|
+
(void)method;
|
|
21
|
+
(void)body;
|
|
22
|
+
(void)headers;
|
|
23
|
+
|
|
24
|
+
char* empty = malloc(1);
|
|
25
|
+
if (empty) empty[0] = '\0';
|
|
26
|
+
return empty;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#else
|
|
30
|
+
|
|
31
|
+
#include <curl/curl.h>
|
|
17
32
|
|
|
18
33
|
/* ------------------------------------------------------------------ */
|
|
19
34
|
/* Internal write callback for curl */
|
|
@@ -50,9 +65,10 @@ static size_t fetch_write_cb(void* contents, size_t size, size_t nmemb, void* us
|
|
|
50
65
|
/* Global curl init (thread-safe, called once) */
|
|
51
66
|
/* ------------------------------------------------------------------ */
|
|
52
67
|
|
|
53
|
-
static
|
|
68
|
+
static cerver_fetch_global_init_guard_t curl_global_init_guard =
|
|
69
|
+
CERVER_FETCH_GLOBAL_INIT_GUARD_INITIALIZER;
|
|
54
70
|
|
|
55
|
-
static void
|
|
71
|
+
static void init_curl_global_state(void) { curl_global_init(CURL_GLOBAL_DEFAULT); }
|
|
56
72
|
|
|
57
73
|
/* ------------------------------------------------------------------ */
|
|
58
74
|
/* Public API */
|
|
@@ -77,7 +93,7 @@ char* cerver_fetch(const char* url, const char* method, const char* body, const
|
|
|
77
93
|
}
|
|
78
94
|
|
|
79
95
|
/* Ensure global curl init */
|
|
80
|
-
|
|
96
|
+
cerver_fetch_global_init_guard_run(&curl_global_init_guard, init_curl_global_state);
|
|
81
97
|
|
|
82
98
|
CURL* curl = curl_easy_init();
|
|
83
99
|
if (!curl) {
|
|
@@ -156,3 +172,4 @@ char* cerver_fetch(const char* url, const char* method, const char* body, const
|
|
|
156
172
|
|
|
157
173
|
return buf.data;
|
|
158
174
|
}
|
|
175
|
+
#endif // CERVER_NO_CURL
|
package/runtime/http_parser.c
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
#include <stdio.h>
|
|
13
13
|
#include <stdlib.h>
|
|
14
14
|
#include <string.h>
|
|
15
|
+
|
|
16
|
+
#if !CERVER_PLATFORM_WINDOWS
|
|
15
17
|
#include <strings.h>
|
|
18
|
+
#endif // !CERVER_PLATFORM_WINDOWS
|
|
19
|
+
|
|
16
20
|
#include <ctype.h>
|
|
17
21
|
|
|
18
22
|
/* ------------------------------------------------------------------ */
|
package/runtime/http_writer.c
CHANGED
package/runtime/mime.c
CHANGED
package/runtime/router.c
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
#include <stdio.h>
|
|
13
13
|
#include <stdlib.h>
|
|
14
14
|
#include <string.h>
|
|
15
|
+
|
|
16
|
+
#if !CERVER_PLATFORM_WINDOWS
|
|
15
17
|
#include <strings.h>
|
|
18
|
+
#endif // !CERVER_PLATFORM_WINDOWS
|
|
16
19
|
|
|
17
20
|
/* ------------------------------------------------------------------ */
|
|
18
21
|
/* Request accessor helpers */
|