1use std::{fmt::Display, sync::Arc};
8
9use async_channel::bounded;
10use bytes::Bytes;
11use h3::server::{Connection as H3Connection, RequestResolver, RequestStream};
12use h3_quinn::{Connection, RecvStream, SendStream};
13use hyper::{header::CONTENT_TYPE, Method, Request, Response, StatusCode};
14use log::{debug, error};
15use serde_json::{json, to_value, Value};
16
17use karyon_core::async_util::{select, Backoff, Either};
18
19use karyon_net::{
20 quic::{QuicConn, QuicEndpoint, QuicIncoming},
21 ByteBuffer, Endpoint,
22};
23
24use crate::{
25 codec::{encode_msg, extend_buf, JsonRpcCodec, DEFAULT_CONTENT_TYPE},
26 error::{Error, Result},
27 message,
28 server::{
29 channel::Channel,
30 dispatch::{sanity_check, Handler, NewRequest, SanityCheckResult},
31 http::{
32 encode_response, parse_error_response, ERR_BODY_TOO_LARGE, ERR_METHOD_NOT_ALLOWED,
33 MAX_HTTP_BODY_SIZE,
34 },
35 Server, CHANNEL_SUBSCRIPTION_BUFFER_SIZE,
36 },
37};
38
39type H3Resolver = RequestResolver<Connection, Bytes>;
40type H3Send = RequestStream<SendStream<Bytes>, Bytes>;
41type H3Recv = RequestStream<RecvStream, Bytes>;
42
43pub(super) async fn accept_h3<C: JsonRpcCodec>(
44 server: &Arc<Server>,
45 quic_ep: &QuicEndpoint,
46 codec: &C,
47 backoff: &Backoff,
48) {
49 let incoming = match quic_ep.accept_incoming().await {
51 Ok(incoming) => incoming,
52 Err(err) => {
53 error!("Accept QUIC for HTTP/3: {err}");
54 backoff.sleep().await;
55 return;
56 }
57 };
58 backoff.reset();
59
60 server
61 .task_group
62 .spawn(serve_incoming_task(server.clone(), incoming, codec.clone()));
63}
64
65async fn serve_incoming_task<C: JsonRpcCodec>(
66 server: Arc<Server>,
67 incoming: QuicIncoming,
68 codec: C,
69) -> Result<()> {
70 let peer = incoming.peer_endpoint();
71 match incoming.handshake().await {
72 Ok(quic_conn) => serve_conn_task(server, quic_conn, codec).await,
73 Err(err) => {
74 debug!("QUIC handshake with {peer} failed: {err}");
75 Ok(())
76 }
77 }
78}
79
80async fn serve_conn_task<C: JsonRpcCodec>(
81 server: Arc<Server>,
82 quic_conn: QuicConn,
83 codec: C,
84) -> Result<()> {
85 let peer = quic_conn
86 .peer_endpoint()
87 .map(|e| e.to_string())
88 .unwrap_or_default();
89 if let Err(err) = serve_conn(server, quic_conn, codec).await {
90 debug!("HTTP/3 from {peer} closed: {err}");
91 }
92 Ok(())
93}
94
95async fn serve_conn<C: JsonRpcCodec>(
96 server: Arc<Server>,
97 quic_conn: QuicConn,
98 codec: C,
99) -> Result<()> {
100 let h3_conn = Connection::new(quic_conn.inner().clone());
101 let mut h3_server: H3Connection<Connection, Bytes> = H3Connection::new(h3_conn)
102 .await
103 .map_err(|e| Error::HttpError(format!("H3 handshake: {e}")))?;
104
105 let peer = quic_conn.peer_endpoint().ok();
106
107 loop {
108 match h3_server.accept().await {
109 Ok(Some(resolver)) => {
112 server.task_group.spawn(handle_request_task(
113 server.clone(),
114 resolver,
115 peer.clone(),
116 codec.clone(),
117 ));
118 }
119 Ok(None) => break,
120 Err(err) => {
121 debug!("HTTP/3 connection error: {err}");
122 break;
123 }
124 }
125 }
126
127 Ok(())
128}
129
130async fn handle_request_task<C: JsonRpcCodec>(
131 server: Arc<Server>,
132 resolver: H3Resolver,
133 peer: Option<Endpoint>,
134 codec: C,
135) -> Result<()> {
136 let (req, stream) = match resolver.resolve_request().await {
137 Ok(v) => v,
138 Err(err) => {
139 debug!("Resolve HTTP/3 request: {err}");
140 return Ok(());
141 }
142 };
143
144 let (send, recv) = stream.split();
145 if let Err(err) = handle_h3_request(server, req, send, recv, peer, codec).await {
146 error!("Handle HTTP/3 request: {err}");
147 }
148 Ok(())
149}
150
151async fn handle_h3_request<C: JsonRpcCodec>(
152 server: Arc<Server>,
153 req: Request<()>,
154 mut send: H3Send,
155 recv: H3Recv,
156 peer: Option<Endpoint>,
157 codec: C,
158) -> Result<()> {
159 let content_type = server.config.http_config.content_type.clone();
160
161 if req.method() != Method::POST {
162 let body = ERR_METHOD_NOT_ALLOWED.as_bytes();
163 return h3_send(
164 &mut send,
165 StatusCode::METHOD_NOT_ALLOWED,
166 DEFAULT_CONTENT_TYPE,
167 body,
168 )
169 .await;
170 }
171
172 let mut reader = BodyReader {
174 recv,
175 buf: ByteBuffer::new(),
176 codec: codec.clone(),
177 };
178 let msg = match reader.next().await {
179 Ok(Some(msg)) => msg,
180 Err(Error::BufferFull(_)) => {
181 let body = ERR_BODY_TOO_LARGE.as_bytes();
182 return h3_send(
183 &mut send,
184 StatusCode::PAYLOAD_TOO_LARGE,
185 DEFAULT_CONTENT_TYPE,
186 body,
187 )
188 .await;
189 }
190 Err(Error::HttpError(err)) => return Err(Error::HttpError(err)),
191 Ok(None) | Err(_) => {
192 let body = encode_response(&codec, &parse_error_response())?;
193 return h3_send(&mut send, StatusCode::OK, &content_type, &body).await;
194 }
195 };
196
197 let req = match sanity_check(msg) {
198 SanityCheckResult::NewReq(req) => req,
199 SanityCheckResult::ErrRes(res) => {
200 let body = encode_response(&codec, &res)?;
201 return h3_send(&mut send, StatusCode::OK, &content_type, &body).await;
202 }
203 };
204
205 let is_pubsub = matches!(
210 server.resolve_handler(&req.srvc_name, &req.method_name, true),
211 Handler::Pubsub(_)
212 );
213 if is_pubsub {
214 return handle_h3_subscription(server, req, send, reader, peer, codec).await;
215 }
216
217 let msg = to_value(&req.msg)?;
218 let response = server.handle_request(None, msg).await;
219 debug!("--> {response}");
220 let body = encode_response(&codec, &response)?;
221 h3_send(&mut send, StatusCode::OK, &content_type, &body).await
222}
223
224async fn handle_h3_subscription<C: JsonRpcCodec>(
228 server: Arc<Server>,
229 req: NewRequest,
230 mut send: H3Send,
231 mut reader: BodyReader<C>,
232 peer: Option<Endpoint>,
233 codec: C,
234) -> Result<()> {
235 let content_type = server.config.http_config.content_type.clone();
236 let (ch_tx, ch_rx) = bounded(CHANNEL_SUBSCRIPTION_BUFFER_SIZE);
237 let channel = Channel::new(ch_tx, peer);
238
239 let method = match server.resolve_handler(&req.srvc_name, &req.method_name, true) {
240 Handler::Pubsub(m) => m,
241 _ => unreachable!("pubsub method presence checked by caller"),
242 };
243
244 let params = req.msg.params.unwrap_or(json!(()));
245 let response = match method(channel.clone(), req.msg.method, params).await {
246 Ok(res) => message::Response {
247 result: Some(res),
248 id: Some(req.msg.id),
249 ..Default::default()
250 },
251 Err(err) => {
252 let response = err.to_response(Some(req.msg.id), None);
253 let body = encode_response(&codec, &response)?;
254 return h3_send(&mut send, StatusCode::OK, &content_type, &body).await;
255 }
256 };
257
258 debug!("--> {response}");
259 send.send_response(ok_response(&content_type)?)
260 .await
261 .map_err(h3_err)?;
262 let body = encode_response(&codec, &response)?;
263 send.send_data(body).await.map_err(h3_err)?;
264
265 let encoder = server.config.notification_encoder;
266 let result = loop {
267 match select(ch_rx.recv(), reader.next()).await {
268 Either::Left(Ok(nt)) => {
269 let notification = encoder(nt);
270 debug!("--> {notification}");
271 let body = encode_msg(&codec, &json!(notification))?;
272 if let Err(err) = send.send_data(body).await {
273 break Err(h3_err(err));
274 }
275 }
276 Either::Left(Err(err)) => break Err(err.into()),
277 Either::Right(Ok(Some(msg))) => {
280 let response = server.handle_request(Some(channel.clone()), msg).await;
281 debug!("--> {response}");
282 let body = encode_response(&codec, &response)?;
283 break send.send_data(body).await.map_err(h3_err);
284 }
285 Either::Right(_) => break Ok(()),
286 }
287 };
288
289 channel.close();
290 let _ = send.finish().await;
291 result
292}
293
294struct BodyReader<C> {
296 recv: H3Recv,
297 buf: ByteBuffer,
298 codec: C,
299}
300
301impl<C: JsonRpcCodec> BodyReader<C> {
302 async fn next(&mut self) -> Result<Option<Value>> {
304 loop {
305 if let Some((n, msg)) = self.codec.decode(&mut self.buf)? {
306 self.buf.advance(n);
307 return Ok(Some(msg));
308 }
309 if self.buf.len() as u64 > MAX_HTTP_BODY_SIZE {
310 return Err(Error::BufferFull("request body too large".into()));
311 }
312 match self.recv.recv_data().await.map_err(h3_err)? {
313 Some(chunk) => extend_buf(&mut self.buf, chunk),
314 None => return Ok(None),
315 }
316 }
317 }
318}
319
320fn ok_response(content_type: &str) -> Result<Response<()>> {
321 Response::builder()
322 .status(StatusCode::OK)
323 .header(CONTENT_TYPE, content_type)
324 .body(())
325 .map_err(|e| Error::HttpError(e.to_string()))
326}
327
328async fn h3_send(
329 send: &mut H3Send,
330 status: StatusCode,
331 content_type: &str,
332 body: &[u8],
333) -> Result<()> {
334 let resp = Response::builder()
335 .status(status)
336 .header(CONTENT_TYPE, content_type)
337 .body(())
338 .map_err(|e| Error::HttpError(e.to_string()))?;
339 send.send_response(resp).await.map_err(h3_err)?;
340 send.send_data(Bytes::from(body.to_vec()))
341 .await
342 .map_err(h3_err)?;
343 send.finish().await.map_err(h3_err)?;
344 Ok(())
345}
346
347fn h3_err(e: impl Display) -> Error {
348 Error::HttpError(e.to_string())
349}