castrum 0.9.3 → 0.9.6
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/Cargo.lock +2242 -0
- package/Cargo.toml +155 -0
- package/README.md +14 -6
- package/build.rs +5 -0
- package/castrum.darwin-arm64.node +0 -0
- package/castrum.darwin-x64.node +0 -0
- package/castrum.linux-arm64-gnu.node +0 -0
- package/castrum.linux-arm64-musl.node +0 -0
- package/castrum.linux-x64-gnu.node +0 -0
- package/castrum.linux-x64-musl.node +0 -0
- package/castrum.linux-x64-v3-gnu.node +0 -0
- package/castrum.win32-x64-msvc.node +0 -0
- package/dist/index.d.ts +1508 -1291
- package/dist/index.js +3391 -2069
- package/docs/API.md +2 -1
- package/docs/ARCHITECTURE.md +3 -2
- package/docs/CASE_STUDY.md +5 -3
- package/docs/ENVIRONMENT.md +25 -2
- package/docs/FFI_BUN_GUIDE.md +242 -14
- package/docs/HOW_TO_ADD_AN_OP.md +10 -0
- package/docs/REPO_MAP.md +17 -6
- package/docs/RND-CONCURRENCY.md +772 -0
- package/docs/bun-builtins-decision-matrix.md +4 -1
- package/index.ts +24 -25
- package/package.json +173 -156
- package/rust/crypto/aead.rs +378 -0
- package/rust/crypto/argon2.rs +265 -0
- package/rust/crypto/base64.rs +420 -0
- package/rust/crypto/bcrypt.rs +89 -0
- package/rust/crypto/cookie_sign.rs +169 -0
- package/rust/crypto/csrf.rs +106 -0
- package/rust/crypto/ed25519.rs +215 -0
- package/rust/crypto/hashing.rs +140 -0
- package/rust/crypto/hmac_sha256.rs +88 -0
- package/rust/crypto/jwt/api.rs +286 -0
- package/rust/crypto/jwt/mod.rs +22 -0
- package/rust/crypto/jwt/tests.rs +312 -0
- package/rust/crypto/jwt/token.rs +360 -0
- package/rust/crypto/mod.rs +27 -0
- package/rust/crypto/pbkdf2.rs +105 -0
- package/rust/crypto/random_token.rs +85 -0
- package/rust/crypto/session.rs +222 -0
- package/rust/ffi/crypto.rs +708 -0
- package/rust/ffi/hashing.rs +285 -0
- package/rust/ffi/http.rs +752 -0
- package/rust/ffi/ingress.rs +303 -0
- package/rust/ffi/json.rs +517 -0
- package/rust/ffi/jwt.rs +419 -0
- package/rust/ffi/metrics.rs +373 -0
- package/rust/ffi/mod.rs +69 -0
- package/rust/ffi/payload.rs +275 -0
- package/rust/ffi/probe.rs +60 -0
- package/rust/ffi/rate_limit.rs +77 -0
- package/rust/ffi/route.rs +85 -0
- package/rust/ffi/task.rs +172 -0
- package/rust/ffi/tests.rs +2333 -0
- package/rust/ffi/util.rs +152 -0
- package/rust/ffi/validators.rs +123 -0
- package/rust/http/accept.rs +606 -0
- package/rust/http/cookie_parser.rs +140 -0
- package/rust/http/etag.rs +289 -0
- package/rust/http/form.rs +136 -0
- package/rust/http/headers.rs +267 -0
- package/rust/http/http_date.rs +286 -0
- package/rust/http/http_parser.rs +252 -0
- package/rust/http/media_type.rs +355 -0
- package/rust/http/method.rs +200 -0
- package/rust/http/mime_lookup.rs +130 -0
- package/rust/http/mod.rs +32 -0
- package/rust/http/multipart.rs +685 -0
- package/rust/http/query_parser.rs +211 -0
- package/rust/http/url_codec.rs +296 -0
- package/rust/http/url_join.rs +324 -0
- package/rust/ingress/api.rs +355 -0
- package/rust/ingress/cors.rs +403 -0
- package/rust/ingress/ingress_constants.rs +209 -0
- package/rust/ingress/ip_trust.rs +312 -0
- package/rust/ingress/mod.rs +48 -0
- package/rust/ingress/native_route.rs +770 -0
- package/rust/ingress/options.rs +176 -0
- package/rust/ingress/output.rs +406 -0
- package/rust/ingress/packed.rs +191 -0
- package/rust/ingress/pipeline.rs +534 -0
- package/rust/ingress/proxy.rs +138 -0
- package/rust/ingress/rate_limit.rs +538 -0
- package/rust/ingress/terminal.rs +114 -0
- package/rust/ingress/tests.rs +567 -0
- package/rust/ingress/time.rs +70 -0
- package/rust/json/fast_schema/capture.rs +336 -0
- package/rust/json/fast_schema/compile.rs +556 -0
- package/rust/json/fast_schema/cursor.rs +368 -0
- package/rust/json/fast_schema/email.rs +282 -0
- package/rust/json/fast_schema/errors.rs +247 -0
- package/rust/json/fast_schema/mod.rs +57 -0
- package/rust/json/fast_schema/tests.rs +1143 -0
- package/rust/json/fast_schema/types.rs +140 -0
- package/rust/json/fast_schema/validate.rs +931 -0
- package/rust/json/json_ops.rs +121 -0
- package/rust/json/json_schema.rs +837 -0
- package/rust/json/json_ser.rs +883 -0
- package/rust/json/mod.rs +19 -0
- package/rust/json/napi_marshal.rs +318 -0
- package/rust/json/patch/api.rs +60 -0
- package/rust/json/patch/engine.rs +153 -0
- package/rust/json/patch/mod.rs +47 -0
- package/rust/json/patch/ops.rs +270 -0
- package/rust/json/patch/pointer.rs +49 -0
- package/rust/json/patch/tests.rs +499 -0
- package/rust/lib.rs +73 -0
- package/rust/metrics/api.rs +148 -0
- package/rust/metrics/mod.rs +21 -0
- package/rust/metrics/registry.rs +961 -0
- package/rust/panic_safety.rs +40 -0
- package/rust/payload/compress.rs +512 -0
- package/rust/payload/mod.rs +13 -0
- package/rust/payload/sse.rs +214 -0
- package/rust/payload/template.rs +253 -0
- package/rust/payload/websocket.rs +69 -0
- package/rust/payload/ws_frames.rs +354 -0
- package/rust/proptest_suite.rs +139 -0
- package/rust/selection.rs +95 -0
- package/rust/src/bin/native-bench.rs +495 -0
- package/rust/task/completion.rs +119 -0
- package/rust/task/mod.rs +65 -0
- package/rust/task/ops.rs +503 -0
- package/rust/task/runtime.rs +220 -0
- package/rust/task/tests.rs +231 -0
- package/rust/test_support.rs +71 -0
- package/rust/util/batch/api.rs +266 -0
- package/rust/util/batch/core.rs +473 -0
- package/rust/util/batch/mod.rs +23 -0
- package/rust/util/batch/tests.rs +445 -0
- package/rust/util/batch_core.rs +184 -0
- package/rust/util/bytes.rs +594 -0
- package/rust/util/mod.rs +34 -0
- package/rust/util/packed.rs +473 -0
- package/rust/util/text.rs +130 -0
- package/rust/util/threadpool.rs +128 -0
- package/rust/util/validation.rs +419 -0
- package/rust-toolchain.toml +17 -0
- package/scripts/postinstall.mjs +199 -0
- package/src/ingress/constants.ts +1 -1
- package/src/ingress/context.ts +2 -2
- package/src/ingress/decode/baked-result.ts +13 -13
- package/src/ingress/decode/fast-result.ts +17 -17
- package/src/ingress/errors.ts +7 -7
- package/src/ingress/headers/baked-templates.ts +1 -1
- package/src/ingress/headers/fast-templates.ts +3 -3
- package/src/ingress/health.ts +1 -2
- package/src/ingress/index.ts +1 -1
- package/src/ingress/native-route.ts +9 -5
- package/src/ingress/options.ts +1 -1
- package/src/ingress/packing/gather-raw-headers.ts +1 -1
- package/src/ingress/packing/route-wire.ts +1 -5
- package/src/ingress/response/error-bodies.ts +5 -5
- package/src/ingress/response/terminal.ts +1 -1
- package/src/ingress/routes/echo.ts +4 -4
- package/src/ingress/routes/fallback.ts +2 -2
- package/src/ingress/routes/head.ts +2 -2
- package/src/ingress/routes/native.ts +2 -1
- package/src/ingress/routes/options.ts +1 -1
- package/src/ingress/routes/read.ts +2 -2
- package/src/ingress/server.ts +10 -6
- package/src/ingress/status.ts +7 -7
- package/src/integration/batch.ts +1 -1
- package/src/integration/index.ts +9 -9
- package/src/integration/pipeline.ts +6 -6
- package/src/integration/websocket.ts +2 -2
- package/src/loader/index.ts +1 -5
- package/src/loader/ops.ts +1 -1
- package/src/native/ffi/build/codecs.ts +130 -12
- package/src/native/ffi/build/compress.ts +22 -10
- package/src/native/ffi/build/instances.ts +46 -4
- package/src/native/ffi/build/metrics.ts +247 -0
- package/src/native/ffi/build/parse.ts +59 -23
- package/src/native/ffi/build/task.ts +79 -0
- package/src/native/ffi/build/util.ts +32 -1
- package/src/native/ffi/build.ts +4 -0
- package/src/native/ffi/selftest.ts +12 -3
- package/src/native/ffi/types.ts +151 -9
- package/src/native/ffi.ts +160 -15
- package/src/native/index.ts +1 -1
- package/src/native/loader.ts +55 -5
- package/src/native/types/instances.ts +34 -0
- package/src/native/types.ts +11 -0
- package/src/runtime/codec.ts +53 -9
- package/src/runtime/types.ts +7 -0
- package/src/rust-ffi/batch/build.ts +16 -9
- package/src/rust-ffi/index.ts +7 -6
- package/src/rust-ffi/options.ts +1 -3
- package/src/rust-ffi/proven.ts +3 -3
- package/src/rust-ffi/scalar/crypto.ts +1 -1
- package/src/rust-ffi/scalar/factories.ts +73 -0
- package/src/rust-ffi/scalar/hashing.ts +1 -1
- package/src/rust-ffi/scalar/http.ts +71 -27
- package/src/rust-ffi/scalar/index.ts +2 -0
- package/src/rust-ffi/scalar/interface.ts +20 -0
- package/src/rust-ffi/scalar/payload.ts +11 -3
- package/src/rust-ffi/scalar/validation.ts +121 -0
- package/src/rust-ffi/text.ts +25 -3
- package/src/selection.ts +1 -1
- package/src/shared/bytes.ts +24 -4
- package/src/shared/codec.ts +18 -3
- package/src/task/index.ts +24 -0
- package/src/task/op.ts +171 -0
- package/src/task/runtime.ts +568 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// rust/ffi/ingress.rs — ingress pipeline C-ABI exports.
|
|
2
|
+
//
|
|
3
|
+
// The opaque-handle fast path (`castrum_ingress_handle_packed` /
|
|
4
|
+
// `castrum_ingress_handle_components`) runs the ENTIRE ingress pipeline in one
|
|
5
|
+
// call, plus the binary-layout constants projection (`castrum_ingress_layout`).
|
|
6
|
+
// All three follow the aliasing-insurance + `panic_guard` conventions of the
|
|
7
|
+
// napi entry points.
|
|
8
|
+
|
|
9
|
+
use std::slice;
|
|
10
|
+
|
|
11
|
+
use super::util::panic_guard;
|
|
12
|
+
|
|
13
|
+
/// Run the ingress pipeline on a packed request frame. `inner` is the opaque
|
|
14
|
+
/// pointer (as an integer) from `Ingress.ingressInnerPtr()` — valid ONLY while
|
|
15
|
+
/// the `Ingress` instance is alive (see the method's safety note). This is the
|
|
16
|
+
/// hot path: it runs the ENTIRE pipeline (parsing, trust/proxy, schema, CORS,
|
|
17
|
+
/// rate limit, response) in one C-ABI call, cutting the N-API crossing +
|
|
18
|
+
/// marshaling that a per-request `handleRequestPacked` call would pay.
|
|
19
|
+
///
|
|
20
|
+
/// Returns bytes written into `out` (0 = error / too-small buffer).
|
|
21
|
+
///
|
|
22
|
+
/// # Safety
|
|
23
|
+
/// `inner` must be the live `IngressInner` pointer from a live `Ingress`
|
|
24
|
+
/// instance; `input` valid for `input_len` reads; `body` valid for `body_len`
|
|
25
|
+
/// reads (null/0 = no body); `out` valid for `out_cap` writes.
|
|
26
|
+
#[no_mangle]
|
|
27
|
+
pub unsafe extern "C" fn castrum_ingress_handle_packed(
|
|
28
|
+
inner: usize,
|
|
29
|
+
input: *const u8,
|
|
30
|
+
input_len: usize,
|
|
31
|
+
body: *const u8,
|
|
32
|
+
body_len: usize,
|
|
33
|
+
out: *mut u8,
|
|
34
|
+
out_cap: usize,
|
|
35
|
+
) -> usize {
|
|
36
|
+
let inner = inner as *const crate::ingress::IngressInner;
|
|
37
|
+
if inner.is_null() || input.is_null() || out.is_null() {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
let inp = slice::from_raw_parts(input, input_len);
|
|
41
|
+
let out_slice = slice::from_raw_parts_mut(out, out_cap);
|
|
42
|
+
let body_slice: &[u8] = if body.is_null() || body_len == 0 {
|
|
43
|
+
&[]
|
|
44
|
+
} else {
|
|
45
|
+
slice::from_raw_parts(body, body_len)
|
|
46
|
+
};
|
|
47
|
+
// Mirror the napi entry (`util::run_packed_into`): when the input OR the
|
|
48
|
+
// body aliases `out`, copy it first so the shared `&[u8]` and the `&mut
|
|
49
|
+
// [u8]` output borrow never alias (aliased &/&mut is instant UB).
|
|
50
|
+
let owned_input;
|
|
51
|
+
let input_ref: &[u8] = if crate::util::slices_overlap(inp, out_slice) {
|
|
52
|
+
owned_input = inp.to_vec();
|
|
53
|
+
&owned_input
|
|
54
|
+
} else {
|
|
55
|
+
inp
|
|
56
|
+
};
|
|
57
|
+
let owned_body;
|
|
58
|
+
let body_ref: &[u8] = if crate::util::slices_overlap(body_slice, out_slice) {
|
|
59
|
+
owned_body = body_slice.to_vec();
|
|
60
|
+
&owned_body
|
|
61
|
+
} else {
|
|
62
|
+
body_slice
|
|
63
|
+
};
|
|
64
|
+
// A panic must not unwind through the C ABI (that would kill the whole Bun
|
|
65
|
+
// process — the `11-concurrent-burst` crash). Catch it and report 0 (error)
|
|
66
|
+
// so the JS wrapper turns it into a 500, matching the napi path's
|
|
67
|
+
// catch_unwind. `handle_packed` borrows `&self` with no interior mutability
|
|
68
|
+
// on the hot path, so the instance stays consistent after an unwind.
|
|
69
|
+
panic_guard(
|
|
70
|
+
|| {
|
|
71
|
+
(&*inner)
|
|
72
|
+
.handle_packed(input_ref, body_ref, out_slice)
|
|
73
|
+
.unwrap_or(0)
|
|
74
|
+
},
|
|
75
|
+
0,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Run the ingress pipeline from raw request components — the `bun:ffi`
|
|
80
|
+
/// cstring sibling of `castrum_ingress_handle_packed`.
|
|
81
|
+
///
|
|
82
|
+
/// `url` / `ip` are NUL-terminated UTF-8 cstrings (`bun:ffi` `cstring` ARGs —
|
|
83
|
+
/// the engine transcodes the JS strings to call-scoped buffers in-engine), so
|
|
84
|
+
/// the JS side skips the frame assembly + `Buffer.write` UTF-8 encode for the
|
|
85
|
+
/// URL/IP. `rid` / `headers` / `body` are `(ptr,len)` byte slices (headers =
|
|
86
|
+
/// the packed `[u16 count] {pairs}` block); `out` receives the packed decision.
|
|
87
|
+
/// Same wire format + semantics as the packed entry — the shared core is
|
|
88
|
+
/// `IngressInner::handle_components`.
|
|
89
|
+
///
|
|
90
|
+
/// Returns bytes written into `out` (0 = error / too-small buffer).
|
|
91
|
+
///
|
|
92
|
+
/// # Safety
|
|
93
|
+
/// `inner` must be the live `IngressInner` pointer from a live `Ingress`
|
|
94
|
+
/// instance; `url`/`ip` must be valid NUL-terminated buffers (the engine
|
|
95
|
+
/// guarantees this for `cstring` args); `rid`/`headers`/`body` valid for their
|
|
96
|
+
/// declared lengths (null/0 = no body); `out` valid for `out_cap` writes.
|
|
97
|
+
#[no_mangle]
|
|
98
|
+
pub unsafe extern "C" fn castrum_ingress_handle_components(
|
|
99
|
+
inner: usize,
|
|
100
|
+
method_kind: u8,
|
|
101
|
+
url: *const std::os::raw::c_char,
|
|
102
|
+
ip: *const std::os::raw::c_char,
|
|
103
|
+
rid: *const u8,
|
|
104
|
+
rid_len: usize,
|
|
105
|
+
headers: *const u8,
|
|
106
|
+
headers_len: usize,
|
|
107
|
+
body: *const u8,
|
|
108
|
+
body_len: usize,
|
|
109
|
+
out: *mut u8,
|
|
110
|
+
out_cap: usize,
|
|
111
|
+
) -> usize {
|
|
112
|
+
let inner = inner as *const crate::ingress::IngressInner;
|
|
113
|
+
if inner.is_null()
|
|
114
|
+
|| url.is_null()
|
|
115
|
+
|| ip.is_null()
|
|
116
|
+
|| rid.is_null()
|
|
117
|
+
|| headers.is_null()
|
|
118
|
+
|| out.is_null()
|
|
119
|
+
{
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
if out_cap < crate::ingress::output::OUT_DATA_START {
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
let url_bytes = std::ffi::CStr::from_ptr(url).to_bytes();
|
|
126
|
+
let ip_bytes = std::ffi::CStr::from_ptr(ip).to_bytes();
|
|
127
|
+
let rid_slice = slice::from_raw_parts(rid, rid_len);
|
|
128
|
+
let headers_slice = slice::from_raw_parts(headers, headers_len);
|
|
129
|
+
let body_slice: &[u8] = if body.is_null() || body_len == 0 {
|
|
130
|
+
&[]
|
|
131
|
+
} else {
|
|
132
|
+
slice::from_raw_parts(body, body_len)
|
|
133
|
+
};
|
|
134
|
+
let out_slice = slice::from_raw_parts_mut(out, out_cap);
|
|
135
|
+
// Aliasing insurance (mirrors the packed entry): if any input aliases the
|
|
136
|
+
// output, copy it first so the shared `&[u8]` and the `&mut [u8]` output
|
|
137
|
+
// borrow never alias (aliased &/&mut is instant UB). The `url`/`ip`
|
|
138
|
+
// cstrings are engine-scoped buffers and can never alias `out`.
|
|
139
|
+
let owned_rid;
|
|
140
|
+
let rid_ref: &[u8] = if crate::util::slices_overlap(rid_slice, out_slice) {
|
|
141
|
+
owned_rid = rid_slice.to_vec();
|
|
142
|
+
&owned_rid
|
|
143
|
+
} else {
|
|
144
|
+
rid_slice
|
|
145
|
+
};
|
|
146
|
+
let owned_headers;
|
|
147
|
+
let headers_ref: &[u8] = if crate::util::slices_overlap(headers_slice, out_slice) {
|
|
148
|
+
owned_headers = headers_slice.to_vec();
|
|
149
|
+
&owned_headers
|
|
150
|
+
} else {
|
|
151
|
+
headers_slice
|
|
152
|
+
};
|
|
153
|
+
let owned_body;
|
|
154
|
+
let body_ref: &[u8] = if crate::util::slices_overlap(body_slice, out_slice) {
|
|
155
|
+
owned_body = body_slice.to_vec();
|
|
156
|
+
&owned_body
|
|
157
|
+
} else {
|
|
158
|
+
body_slice
|
|
159
|
+
};
|
|
160
|
+
let mk = crate::http::method::MethodKind::from_u8(method_kind);
|
|
161
|
+
// A panic must not unwind through the C ABI — catch it and report 0 (the
|
|
162
|
+
// JS wrapper turns it into a 500), matching the packed entry.
|
|
163
|
+
panic_guard(
|
|
164
|
+
|| {
|
|
165
|
+
(&*inner)
|
|
166
|
+
.handle_components(
|
|
167
|
+
mk,
|
|
168
|
+
url_bytes,
|
|
169
|
+
ip_bytes,
|
|
170
|
+
rid_ref,
|
|
171
|
+
headers_ref,
|
|
172
|
+
body_ref,
|
|
173
|
+
out_slice,
|
|
174
|
+
)
|
|
175
|
+
.unwrap_or(0)
|
|
176
|
+
},
|
|
177
|
+
0,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Ingress binary-layout constants (C ABI) ──────────────────────
|
|
182
|
+
// The napi projection (`ingress_constants.rs`) exposes these to JS by name;
|
|
183
|
+
// this C-ABI variant lets Bun read the SAME values via `bun:ffi` WITHOUT
|
|
184
|
+
// loading the napi addon, so `import castrum` is FFI-only under Bun. Values
|
|
185
|
+
// are read directly from `output.rs` (the single numeric source). Field ORDER
|
|
186
|
+
// is the wire contract — pinned by `ingress_layout_c_abi_matches_output_source`
|
|
187
|
+
// below and by the bun:ffi bind-time self-test (which falls back to napi if the
|
|
188
|
+
// pinned values don't line up).
|
|
189
|
+
|
|
190
|
+
/// `#[repr(C)]` projection of the ingress layout constants for the FFI path.
|
|
191
|
+
/// `castrum_ingress_layout` memcpys this struct into the caller's buffer; the
|
|
192
|
+
/// JS side reads it as 38 × u32 little-endian at the same slot order.
|
|
193
|
+
#[repr(C)]
|
|
194
|
+
pub struct IngressLayout {
|
|
195
|
+
// Output buffer layout (u32)
|
|
196
|
+
pub out_verdict: u32,
|
|
197
|
+
pub out_error_code: u32,
|
|
198
|
+
pub out_status: u32,
|
|
199
|
+
pub out_flags: u32,
|
|
200
|
+
pub out_rate_limit: u32,
|
|
201
|
+
pub out_rate_remaining: u32,
|
|
202
|
+
pub out_rate_reset: u32,
|
|
203
|
+
pub out_retry_after: u32,
|
|
204
|
+
pub out_cookies_json_len: u32,
|
|
205
|
+
pub out_query_json_len: u32,
|
|
206
|
+
pub out_header_variant: u32,
|
|
207
|
+
pub out_body_json_len: u32,
|
|
208
|
+
pub out_data_start: u32,
|
|
209
|
+
// Flags
|
|
210
|
+
pub flag_has_cookies: u32,
|
|
211
|
+
pub flag_has_query: u32,
|
|
212
|
+
pub flag_body_valid_json: u32,
|
|
213
|
+
pub flag_schema_valid: u32,
|
|
214
|
+
pub flag_cors_allowed: u32,
|
|
215
|
+
pub flag_is_preflight: u32,
|
|
216
|
+
pub flag_rate_limited: u32,
|
|
217
|
+
pub flag_https: u32,
|
|
218
|
+
pub flag_trusted_proxy: u32,
|
|
219
|
+
pub flag_body_truncated: u32,
|
|
220
|
+
// Header variant bits
|
|
221
|
+
pub hv_json: u32,
|
|
222
|
+
pub hv_cors_simple: u32,
|
|
223
|
+
pub hv_cors_preflight: u32,
|
|
224
|
+
pub hv_rate_active: u32,
|
|
225
|
+
pub hv_rate_limited: u32,
|
|
226
|
+
pub hv_count: u32,
|
|
227
|
+
// Error codes
|
|
228
|
+
pub err_none: u32,
|
|
229
|
+
pub err_cors_preflight: u32,
|
|
230
|
+
pub err_rate_limited: u32,
|
|
231
|
+
pub err_body_too_large: u32,
|
|
232
|
+
pub err_invalid_json: u32,
|
|
233
|
+
pub err_schema_validation: u32,
|
|
234
|
+
pub err_bad_request: u32,
|
|
235
|
+
pub err_request_too_large: u32,
|
|
236
|
+
pub err_internal: u32,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
impl IngressLayout {
|
|
240
|
+
/// Build the layout from `output.rs` (the single numeric source).
|
|
241
|
+
const fn from_output() -> Self {
|
|
242
|
+
use crate::ingress::output as o;
|
|
243
|
+
Self {
|
|
244
|
+
out_verdict: o::OUT_VERDICT as u32,
|
|
245
|
+
out_error_code: o::OUT_ERROR_CODE as u32,
|
|
246
|
+
out_status: o::OUT_STATUS as u32,
|
|
247
|
+
out_flags: o::OUT_FLAGS as u32,
|
|
248
|
+
out_rate_limit: o::OUT_RATE_LIMIT as u32,
|
|
249
|
+
out_rate_remaining: o::OUT_RATE_REMAINING as u32,
|
|
250
|
+
out_rate_reset: o::OUT_RATE_RESET as u32,
|
|
251
|
+
out_retry_after: o::OUT_RETRY_AFTER as u32,
|
|
252
|
+
out_cookies_json_len: o::OUT_COOKIES_JSON_LEN as u32,
|
|
253
|
+
out_query_json_len: o::OUT_QUERY_JSON_LEN as u32,
|
|
254
|
+
out_header_variant: o::OUT_HEADER_VARIANT as u32,
|
|
255
|
+
out_body_json_len: o::OUT_BODY_JSON_LEN as u32,
|
|
256
|
+
out_data_start: o::OUT_DATA_START as u32,
|
|
257
|
+
flag_has_cookies: o::FLAG_HAS_COOKIES,
|
|
258
|
+
flag_has_query: o::FLAG_HAS_QUERY,
|
|
259
|
+
flag_body_valid_json: o::FLAG_BODY_VALID_JSON,
|
|
260
|
+
flag_schema_valid: o::FLAG_SCHEMA_VALID,
|
|
261
|
+
flag_cors_allowed: o::FLAG_CORS_ALLOWED,
|
|
262
|
+
flag_is_preflight: o::FLAG_IS_PREFLIGHT,
|
|
263
|
+
flag_rate_limited: o::FLAG_RATE_LIMITED,
|
|
264
|
+
flag_https: o::FLAG_HTTPS,
|
|
265
|
+
flag_trusted_proxy: o::FLAG_TRUSTED_PROXY,
|
|
266
|
+
flag_body_truncated: o::FLAG_BODY_TRUNCATED,
|
|
267
|
+
hv_json: o::HV_JSON as u32,
|
|
268
|
+
hv_cors_simple: o::HV_CORS_SIMPLE as u32,
|
|
269
|
+
hv_cors_preflight: o::HV_CORS_PREFLIGHT as u32,
|
|
270
|
+
hv_rate_active: o::HV_RATE_ACTIVE as u32,
|
|
271
|
+
hv_rate_limited: o::HV_RATE_LIMITED as u32,
|
|
272
|
+
hv_count: o::HV_COUNT as u32,
|
|
273
|
+
err_none: o::ERR_CODE_NONE as u32,
|
|
274
|
+
err_cors_preflight: o::ERR_CODE_CORS_PREFLIGHT as u32,
|
|
275
|
+
err_rate_limited: o::ERR_CODE_RATE_LIMITED as u32,
|
|
276
|
+
err_body_too_large: o::ERR_CODE_BODY_TOO_LARGE as u32,
|
|
277
|
+
err_invalid_json: o::ERR_CODE_INVALID_JSON as u32,
|
|
278
|
+
err_schema_validation: o::ERR_CODE_SCHEMA_VALIDATION as u32,
|
|
279
|
+
err_bad_request: o::ERR_CODE_BAD_REQUEST as u32,
|
|
280
|
+
err_request_too_large: o::ERR_CODE_REQUEST_TOO_LARGE as u32,
|
|
281
|
+
err_internal: o::ERR_CODE_INTERNAL as u32,
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// Write the `IngressLayout` blob (38 × u32 LE) into `out`; returns bytes
|
|
287
|
+
/// written (0 when `out` is too small or null).
|
|
288
|
+
///
|
|
289
|
+
/// # Safety
|
|
290
|
+
/// `out` must be valid for writes up to `out_cap`.
|
|
291
|
+
#[no_mangle]
|
|
292
|
+
pub unsafe extern "C" fn castrum_ingress_layout(out: *mut u8, out_cap: usize) -> usize {
|
|
293
|
+
if out.is_null() {
|
|
294
|
+
return 0;
|
|
295
|
+
}
|
|
296
|
+
const LAYOUT: IngressLayout = IngressLayout::from_output();
|
|
297
|
+
let n = core::mem::size_of::<IngressLayout>();
|
|
298
|
+
if out_cap < n {
|
|
299
|
+
return 0;
|
|
300
|
+
}
|
|
301
|
+
core::ptr::copy_nonoverlapping(&LAYOUT as *const IngressLayout as *const u8, out, n);
|
|
302
|
+
n
|
|
303
|
+
}
|