1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! Consolidated unsafe primitives for uSockets/uWS callback trampolines.
//!
//! Every uWS callback follows the same shape: C hands us a raw handle plus a
//! `*mut c_void` user-data word, and the trampoline must (a) recover the typed
//! owner from the user-data, (b) re-type the opaque handle, (c) lift any
//! `(ptr,len)` pairs into slices, then (d) call the safe Rust handler. Before
//! this module each of `Response::on_*`, `h3::Response::on_*`,
//! `WebSocket::Wrap::on_*`, and `uws_handlers::*Handler` open-coded those
//! steps with three or four `unsafe {}` blocks apiece — ~300 in total.
//!
//! Centralising here means each invariant is documented and audited **once**:
//!
//! * `zst::<H>()` — conjure a ZST handler value (the
//! `comptime handler` → monomorphised-ZST trick).
//! * `user_mut` — null-checked `*mut c_void → Option<&mut U>`.
//! * `handle_mut` — `*mut Opaque → &mut Opaque` for uWS handles.
//! * `c_slice` — `(ptr,len) → &[u8]` (empty when len==0 / null).
//! * `ext_owner` — `&Option<NonNull<T>> → Option<&mut T>` (the
//! `socket.ext(**T).*` pattern).
//! * `socket_ext_owner` / `connecting_ext_owner` — same, but starting from a
//! raw `*us_socket_t` / `*us_connecting_socket_t`.
//!
//! All functions are `unsafe fn` (callers uphold the uWS callback contract)
//! and `#[inline(always)]` so codegen is identical to the hand-rolled thunks.
use c_void;
use NonNull;
use crateus_socket_t;
/// Marker for `#[repr(C)]` zero-sized opaque FFI handles
/// (`UnsafeCell<[u8; 0]>` + `PhantomPinned`).
///
/// uWS hands us raw pointers to C++-owned objects that Rust models as ZST
/// opaques: the `&mut Self` exists only to hang inherent methods off and is
/// immediately re-erased to `*mut` at the FFI boundary. Because `Self` is
/// zero-sized with align 1, **any** non-null pointer is trivially
/// dereferenceable (zero bytes accessed) and `&mut Self` cannot alias any
/// Rust-visible memory — so [`Self::as_handle`] is a *safe* fn even though it
/// wraps `&mut *p`.
///
/// This is what lets `AnyResponse` be a plain `Copy` enum of raw pointers
/// whose method bodies dispatch per-variant without an `unsafe` block at
/// every call site (S019).
///
/// # Safety
/// Implementor MUST be a `#[repr(C)]` zero-sized type with alignment 1 that
/// owns no Rust bytes (i.e. an opaque-extern-type stand-in). Both invariants
/// are additionally enforced at compile time by `const { assert! }` in
/// [`Self::as_handle`], so a bad impl fails to build rather than causing UB.
pub unsafe
/// Conjure a value of a zero-sized handler type.
///
/// Replaces `// SAFETY: H is a ZST → core::mem::zeroed()` repeated at every
/// trampoline site. The ZST invariant is enforced at compile time via the
/// inline `const { assert!() }`, so a non-ZST `H` is a *compile* error at the
/// monomorphisation site — which is what lets this be a *safe* fn (S016).
/// Thin re-export of [`bun_core::ffi::conjure_zst`] kept for the shorter
/// `thunk::zst::<H>()` spelling at the ~20 uWS trampoline call sites.
pub
/// Recover `&mut U` from a uWS user-data word, returning `None` for null.
///
/// # Safety
/// When non-null, `p` must have been registered as `*mut U` and point to a
/// live `U` with no other live `&mut`/`&` to it for the duration of the
/// returned borrow (uWS callbacks fire single-threaded from the event loop).
pub unsafe
/// Re-type a raw uWS handle (`uws_res`, `H3Response`, `RawWebSocket`, …) as a
/// mutable Rust reference. These are zero-sized opaque markers, so the borrow
/// covers no Rust-owned bytes — it exists purely to hang methods off.
///
/// # Safety
/// `p` must be non-null and live for the duration of the callback (guaranteed
/// by uWS for every handle it passes into a callback).
pub unsafe
/// Lift a C `(ptr,len)` pair into a borrowed slice, mapping `len == 0` (and
/// optionally null `ptr`) to `&[]` so callers needn't special-case it.
///
/// # Safety
/// When `len > 0`, `ptr` must be valid for `len` reads and the bytes must
/// outlive `'a` (uWS guarantees this for the duration of the callback).
pub unsafe
/// Dereference the `Option<NonNull<T>>` stored in a socket's ext slot
/// (`socket.ext(**T).*` in Zig). `None` covers the calloc'd-but-not-yet-
/// stamped window during connect/accept.
///
/// # Safety
/// The pointee, when present, must be live and uniquely borrowed for `'a`
/// (uWS dispatch is single-threaded so no aliasing `&mut` exists).
pub unsafe
/// `Option<NonNull<T>>` at context creation; pointee (if any) is live and
/// uniquely accessed.
pub unsafe
// ───────────────────────── safe-surface trampoline ──────────────────────────
//
// S005: the primitives above are `unsafe fn` because each call site must
// re-assert the uWS callback contract. For the common, *non-re-entrant*
// dispatch path (single-threaded event loop, handler does not call back into
// uWS on the same socket while holding `&mut Owner`) that contract is uniform
// and can be discharged once at the type level instead of at every call site.
// `ExtSlot<T>` is that type-level discharge: choosing it as `Handler::Ext`
// moves the proof obligation from ~30 `unsafe { ext_owner(ext) }` blocks to
// the one `unsafe` inside `owner_mut()`.
/// Typed-safe wrapper for the `Option<NonNull<T>>` word stored in a uWS socket
/// ext slot. The newtype is the safe-surface entry point for the
/// `socket.ext(**T).*` pattern: choosing `type Ext = ExtSlot<T>` in a
/// [`crate::vtable::Handler`] impl asserts the **non-re-entrancy contract** —
/// that the handler bodies do not re-enter uWS dispatch on the same socket
/// while a `&mut T` borrowed from this slot is live (re-entrant consumers must
/// keep `type Ext = Option<NonNull<T>>` and pass `*mut T` onward; see
/// `RawPtrHandler`).
///
/// Because the inner field is private and there is no public safe constructor,
/// safe Rust cannot fabricate an `ExtSlot<T>` containing a dangling pointer;
/// every `&mut ExtSlot<T>` reachable from safe code was materialised by the
/// `vtable::Trampolines` layer from C-allocated socket ext memory (via
/// `(*s).ext::<ExtSlot<T>>()`), and `calloc`-zero is `None`. That makes
/// [`Self::owner_mut`] sound as a *safe* fn — the one `unsafe { p.as_mut() }`
/// inside discharges the same invariant every former
/// `unsafe { thunk::ext_owner(ext) }` call site repeated open-coded.
;