1use crate::{CodecLayer, SlotGen, SlotId};
2use std::pin::Pin;
3
4#[derive(Clone, Copy, PartialEq, Eq, Debug)]
5pub enum RouteRequestBodyKind {
6 Inline,
7 Spilled,
8 Stream,
9}
10
11pub trait ServerProtocol: 'static {
22 type Head<'buf>;
23
24 type ConnState: Default + 'static;
25
26 type CodecLayer: CodecLayer;
27
28 const SUPPORTS_PARK: bool = false;
29
30 fn parse<'buf>(
35 &self,
36 state: &mut Self::ConnState,
37 buf: &'buf [u8],
38 ) -> Option<(Self::Head<'buf>, u32, u32)>;
39
40 fn handle<'buf>(
41 &mut self,
42 req: &'buf [u8],
43 head: Self::Head<'buf>,
44 write: &mut [u8],
45 ) -> HandlerAction;
46
47 fn handle_park<'buf>(
48 &mut self,
49 conn_id: SlotId,
50 conn_state: &mut Self::ConnState,
51 req: &'buf [u8],
52 head: Self::Head<'buf>,
53 write: &mut [u8],
54 ) -> ParkAction {
55 let _ = (conn_id, conn_state, req, head, write);
56 unreachable!("ServerProtocol::handle_park called with SUPPORTS_PARK = true but no override")
57 }
58
59 fn oversize_response(&self) -> &'static [u8] {
60 b""
61 }
62
63 fn route_request_body_kind(&self, head: &Self::Head<'_>) -> RouteRequestBodyKind {
64 let _ = head;
65 RouteRequestBodyKind::Inline
66 }
67
68 fn handle_request_stream<'buf>(
69 &mut self,
70 head_bytes: &'buf [u8],
71 head: Self::Head<'buf>,
72 body_stream: RequestBodyStream,
73 write: &mut [u8],
74 ) -> RequestStreamAction {
75 let _ = (head_bytes, head, body_stream, write);
76 unreachable!(
77 "ServerProtocol::handle_request_stream called without an override; \
78 a route returned RouteRequestBodyKind::Stream but the \
79 handler does not implement the stream dispatch path"
80 )
81 }
82
83 fn on_register(
84 &mut self,
85 conn_id: SlotId,
86 conn_state: &mut Self::ConnState,
87 ) -> Option<Pin<Box<dyn std::future::Future<Output = ()> + 'static>>> {
88 let _ = (conn_id, conn_state);
89 None
90 }
91
92 fn drain_outbound(&mut self, conn_state: &mut Self::ConnState, write: &mut [u8]) -> u32 {
93 let _ = (conn_state, write);
94 0
95 }
96
97 fn close_pending(&self, conn_state: &Self::ConnState) -> bool {
98 let _ = conn_state;
99 false
100 }
101}
102
103pub enum ParkAction {
104 Send { written: u16, close_after: bool },
105 Park,
106 Close(&'static [u8]),
107}
108
109pub enum RequestStreamAction {
110 Pending(dambi::InlineFuture<'static, PendingResponse, 64>),
111 Close(&'static [u8]),
112}
113
114pub enum HandlerAction {
115 Send {
116 written: u16,
117 close_after: bool,
118 },
119 SendStatic {
120 hdr_written: u32,
121 body: &'static [u8],
122 close_after: bool,
123 },
124
125 SendVectored {
126 iovs: [dope_core::IoVec; 4],
127 iov_count: u8,
128 cookie: *const u8,
129 total_bytes: u32,
130 close_after: bool,
131 },
132 SendStream {
133 hdr_written: u32,
134 stream: Pin<Box<dyn ResponseChunkStream>>,
135 close_after: bool,
136 },
137 Pending(dambi::InlineFuture<'static, PendingResponse, 64>),
138 Close(&'static [u8]),
139}
140
141pub trait ResponseChunkStream: 'static {
142 fn poll_chunk(
143 self: Pin<&mut Self>,
144 cx: &mut std::task::Context<'_>,
145 ) -> std::task::Poll<Option<dambi::Bytes>>;
146}
147
148pub struct RequestBodyStream {
149 inner: std::rc::Rc<std::cell::RefCell<RequestStreamInner>>,
150}
151
152#[derive(Default)]
153pub(crate) struct RequestStreamInner {
154 pub(crate) pending: std::collections::VecDeque<dambi::Bytes>,
155 pub(crate) waker: Option<std::task::Waker>,
156 pub(crate) received: u32,
157 pub(crate) target: u32,
158 pub(crate) eof: bool,
159}
160
161impl RequestBodyStream {
162 pub(crate) fn new(target: u32) -> (Self, RequestStreamHandle) {
163 let inner = std::rc::Rc::new(std::cell::RefCell::new(RequestStreamInner {
164 pending: std::collections::VecDeque::new(),
165 waker: None,
166 received: 0,
167 target,
168 eof: target == 0,
169 }));
170 (
171 Self {
172 inner: inner.clone(),
173 },
174 RequestStreamHandle { inner },
175 )
176 }
177
178 pub fn poll_chunk(
179 &mut self,
180 cx: &mut std::task::Context<'_>,
181 ) -> std::task::Poll<Option<dambi::Bytes>> {
182 let mut state = self.inner.borrow_mut();
183 if let Some(chunk) = state.pending.pop_front() {
184 return std::task::Poll::Ready(Some(chunk));
185 }
186 if state.eof {
187 return std::task::Poll::Ready(None);
188 }
189 state.waker = Some(cx.waker().clone());
190 std::task::Poll::Pending
191 }
192}
193
194pub(crate) struct RequestStreamHandle {
195 pub(crate) inner: std::rc::Rc<std::cell::RefCell<RequestStreamInner>>,
196}
197
198const REQUEST_STREAM_QUEUE_CAP: usize = 8 * 1024 * 1024;
199
200impl RequestStreamHandle {
201 pub(crate) fn push_slice(&self, src: &[u8]) -> usize {
202 let mut state = self.inner.borrow_mut();
203 if src.is_empty() {
204 return 0;
205 }
206 let queued: usize = state.pending.iter().map(|b| b.len()).sum();
207 if queued >= REQUEST_STREAM_QUEUE_CAP {
208 return 0;
209 }
210 let needed = (state.target.saturating_sub(state.received)) as usize;
211 let take = src.len().min(needed);
212 if take > 0 {
213 state
214 .pending
215 .push_back(dambi::Bytes::copy_from_slice(&src[..take]));
216 state.received = state.received.saturating_add(take as u32);
217 }
218 if state.received >= state.target {
219 state.eof = true;
220 }
221 if let Some(waker) = state.waker.take() {
222 drop(state);
223 waker.wake();
224 }
225 take
226 }
227
228 pub(crate) fn close(&self) {
229 let mut state = self.inner.borrow_mut();
230 state.eof = true;
231 if let Some(waker) = state.waker.take() {
232 drop(state);
233 waker.wake();
234 }
235 }
236
237 pub(crate) fn is_complete(&self) -> bool {
238 let state = self.inner.borrow();
239 state.eof
240 }
241}
242
243type ResponseSerializer = Box<dyn FnOnce(&mut [u8]) -> PendingOutcome + 'static>;
244
245pub struct PendingResponse {
246 pub serializer: ResponseSerializer,
247}
248
249pub enum PendingOutcome {
250 Inline {
251 written: u16,
252 close_after: bool,
253 },
254 Static {
255 hdr_written: u32,
256 body: &'static [u8],
257 close_after: bool,
258 },
259 Stream {
260 hdr_written: u32,
261 stream: Pin<Box<dyn ResponseChunkStream>>,
262 close_after: bool,
263 },
264}
265
266pub(crate) struct PendingFuture {
267 pub(crate) generation: SlotGen,
268 pub(crate) future: dambi::InlineFuture<'static, PendingResponse, 64>,
269}
270
271pub(crate) struct LongFuture {
272 pub(crate) generation: SlotGen,
273 pub(crate) future: Pin<Box<dyn std::future::Future<Output = ()> + 'static>>,
274}