1use crate::jsonrpc::{
2 HandleDispatchFrom, Handled, IntoHandled, JsonRpcResponse, Protocol, protocol,
3};
4
5use crate::role::{HasPeer, Role, handle_incoming_dispatch};
6use crate::{ConnectionTo, Dispatch, JsonRpcNotification, JsonRpcRequest, UntypedMessage};
7use super::Responder;
9use std::future::Future;
10use std::marker::PhantomData;
11use std::ops::AsyncFnMut;
12
13#[derive(Debug)]
15pub struct NullHandler;
16
17impl Default for NullHandler {
18 fn default() -> Self {
19 Self
20 }
21}
22
23impl<Counterpart: Role> HandleDispatchFrom<Counterpart> for NullHandler {
24 fn describe_chain(&self) -> impl std::fmt::Debug {
25 "(null)"
26 }
27
28 fn handle_dispatch_from(
29 &mut self,
30 message: Dispatch,
31 _cx: ConnectionTo<Counterpart>,
32 ) -> impl Future<Output = Result<Handled<Dispatch>, crate::Error>> + Send {
33 std::future::ready(Ok(Handled::No {
34 message,
35 retry: false,
36 }))
37 }
38}
39
40pub struct RequestHandler<
42 Counterpart: Role,
43 Peer: Role,
44 P,
45 Req: JsonRpcRequest = UntypedMessage,
46 F = (),
47 ToFut = (),
48> {
49 counterpart: Counterpart,
50 peer: Peer,
51 handler: F,
52 to_future_hack: ToFut,
53 phantom: PhantomData<fn(Req, P)>,
54}
55
56impl<Counterpart: Role, Peer: Role, Req: JsonRpcRequest, F, ToFut, P>
57 RequestHandler<Counterpart, Peer, P, Req, F, ToFut>
58{
59 pub fn new(counterpart: Counterpart, peer: Peer, handler: F, to_future_hack: ToFut) -> Self {
61 Self {
62 counterpart,
63 peer,
64 handler,
65 to_future_hack,
66 phantom: PhantomData,
67 }
68 }
69}
70
71impl<Counterpart: Role, Peer: Role, Req, F, T, ToFut, P> HandleDispatchFrom<Counterpart>
72 for RequestHandler<Counterpart, Peer, P, Req, F, ToFut>
73where
74 Counterpart: HasPeer<Peer>,
75 Req: JsonRpcRequest,
76 P: Protocol,
77 F: AsyncFnMut(
78 Req,
79 Responder<Req::Response, P>,
80 P::Connection<Counterpart>,
81 ) -> Result<T, crate::Error>
82 + Send,
83 T: crate::IntoHandled<(Req, Responder<Req::Response, P>)>,
84 ToFut: Fn(
85 &mut F,
86 Req,
87 Responder<Req::Response, P>,
88 P::Connection<Counterpart>,
89 ) -> crate::BoxFuture<'_, Result<T, crate::Error>>
90 + Send
91 + Sync,
92{
93 fn describe_chain(&self) -> impl std::fmt::Debug {
94 std::any::type_name::<Req>()
95 }
96
97 async fn handle_dispatch_from(
98 &mut self,
99 dispatch: Dispatch,
100 connection: ConnectionTo<Counterpart>,
101 ) -> Result<Handled<Dispatch>, crate::Error> {
102 handle_incoming_dispatch(
103 self.counterpart.clone(),
104 self.peer.clone(),
105 dispatch,
106 connection,
107 async |dispatch, connection| {
108 match dispatch {
109 Dispatch::Request(message, responder) => {
110 tracing::debug!(
111 request_type = std::any::type_name::<Req>(),
112 method = %message.method,
113 "RequestHandler::handle_request"
114 );
115 if Req::matches_method(&message.method) {
116 match Req::parse_message(&message.method, &message.params) {
117 Ok(req) => {
118 tracing::trace!(
119 "RequestHandler::handle_request: parse completed"
120 );
121 let typed_responder = responder.cast().retag::<P>()?;
122 let result = (self.to_future_hack)(
123 &mut self.handler,
124 req,
125 typed_responder,
126 protocol::connection_from_raw::<P, _>(connection),
127 )
128 .await?;
129 match result.into_handled() {
130 Handled::Yes => Ok(Handled::Yes),
131 Handled::No {
132 message: (request, responder),
133 retry,
134 } => {
135 let untyped = request.to_untyped_message()?;
137 Ok(Handled::No {
138 message: Dispatch::Request(
139 untyped,
140 responder.erase_to_json().into_raw(),
141 ),
142 retry,
143 })
144 }
145 }
146 }
147 Err(err) => {
148 tracing::trace!(
149 err = ?crate::util::redacted_error(err.code),
150 "RequestHandler::handle_request: parse errored"
151 );
152 Err(err)
153 }
154 }
155 } else {
156 tracing::trace!("RequestHandler::handle_request: method doesn't match");
157 Ok(Handled::No {
158 message: Dispatch::Request(message, responder),
159 retry: false,
160 })
161 }
162 }
163
164 Dispatch::Notification(..) | Dispatch::Response(..) => Ok(Handled::No {
165 message: dispatch,
166 retry: false,
167 }),
168 }
169 },
170 )
171 .await
172 }
173}
174
175pub struct NotificationHandler<
177 Counterpart: Role,
178 Peer: Role,
179 P,
180 Notif: JsonRpcNotification = UntypedMessage,
181 F = (),
182 ToFut = (),
183> {
184 counterpart: Counterpart,
185 peer: Peer,
186 handler: F,
187 to_future_hack: ToFut,
188 phantom: PhantomData<fn(Notif, P)>,
189}
190
191impl<Counterpart: Role, Peer: Role, Notif: JsonRpcNotification, F, ToFut, P>
192 NotificationHandler<Counterpart, Peer, P, Notif, F, ToFut>
193{
194 pub fn new(counterpart: Counterpart, peer: Peer, handler: F, to_future_hack: ToFut) -> Self {
196 Self {
197 counterpart,
198 peer,
199 handler,
200 to_future_hack,
201 phantom: PhantomData,
202 }
203 }
204}
205
206impl<Counterpart: Role, Peer: Role, Notif, F, T, ToFut, P> HandleDispatchFrom<Counterpart>
207 for NotificationHandler<Counterpart, Peer, P, Notif, F, ToFut>
208where
209 Counterpart: HasPeer<Peer>,
210 Notif: JsonRpcNotification,
211 P: Protocol,
212 F: AsyncFnMut(Notif, P::Connection<Counterpart>) -> Result<T, crate::Error> + Send,
213 T: crate::IntoHandled<(Notif, P::Connection<Counterpart>)>,
214 ToFut: Fn(
215 &mut F,
216 Notif,
217 P::Connection<Counterpart>,
218 ) -> crate::BoxFuture<'_, Result<T, crate::Error>>
219 + Send
220 + Sync,
221{
222 fn describe_chain(&self) -> impl std::fmt::Debug {
223 std::any::type_name::<Notif>()
224 }
225
226 async fn handle_dispatch_from(
227 &mut self,
228 dispatch: Dispatch,
229 connection: ConnectionTo<Counterpart>,
230 ) -> Result<Handled<Dispatch>, crate::Error> {
231 handle_incoming_dispatch(
232 self.counterpart.clone(),
233 self.peer.clone(),
234 dispatch,
235 connection,
236 async |dispatch, connection| {
237 match dispatch {
238 Dispatch::Notification(message) => {
239 tracing::debug!(
240 request_type = std::any::type_name::<Notif>(),
241 method = %message.method,
242 "NotificationHandler::handle_dispatch"
243 );
244 if Notif::matches_method(&message.method) {
245 match Notif::parse_message(&message.method, &message.params) {
246 Ok(notif) => {
247 tracing::trace!(
248 "NotificationHandler::handle_notification: parse completed"
249 );
250 let result = (self.to_future_hack)(
251 &mut self.handler,
252 notif,
253 protocol::connection_from_raw::<P, _>(connection),
254 )
255 .await?;
256 match result.into_handled() {
257 Handled::Yes => Ok(Handled::Yes),
258 Handled::No {
259 message: (notification, _cx),
260 retry,
261 } => {
262 let untyped = notification.to_untyped_message()?;
264 Ok(Handled::No {
265 message: Dispatch::Notification(untyped),
266 retry,
267 })
268 }
269 }
270 }
271 Err(err) => {
272 tracing::trace!(
273 err = ?crate::util::redacted_error(err.code),
274 "NotificationHandler::handle_notification: parse errored"
275 );
276 Err(err)
277 }
278 }
279 } else {
280 tracing::trace!(
281 "NotificationHandler::handle_notification: method doesn't match"
282 );
283 Ok(Handled::No {
284 message: Dispatch::Notification(message),
285 retry: false,
286 })
287 }
288 }
289
290 Dispatch::Request(..) | Dispatch::Response(..) => Ok(Handled::No {
291 message: dispatch,
292 retry: false,
293 }),
294 }
295 },
296 )
297 .await
298 }
299}
300
301pub struct MessageHandler<
303 Counterpart: Role,
304 Peer: Role,
305 P,
306 Req: JsonRpcRequest = UntypedMessage,
307 Notif: JsonRpcNotification = UntypedMessage,
308 F = (),
309 ToFut = (),
310> {
311 counterpart: Counterpart,
312 peer: Peer,
313 handler: F,
314 to_future_hack: ToFut,
315 phantom: PhantomData<fn(Dispatch<Req, Notif>, P)>,
316}
317
318impl<Counterpart: Role, Peer: Role, Req: JsonRpcRequest, Notif: JsonRpcNotification, F, ToFut, P>
319 MessageHandler<Counterpart, Peer, P, Req, Notif, F, ToFut>
320{
321 pub fn new(counterpart: Counterpart, peer: Peer, handler: F, to_future_hack: ToFut) -> Self {
323 Self {
324 counterpart,
325 peer,
326 handler,
327 to_future_hack,
328 phantom: PhantomData,
329 }
330 }
331}
332
333impl<Counterpart: Role, Peer: Role, Req: JsonRpcRequest, Notif: JsonRpcNotification, F, T, ToFut, P>
334 HandleDispatchFrom<Counterpart> for MessageHandler<Counterpart, Peer, P, Req, Notif, F, ToFut>
335where
336 Counterpart: HasPeer<Peer>,
337 P: Protocol,
338 F: AsyncFnMut(Dispatch<Req, Notif, P>, P::Connection<Counterpart>) -> Result<T, crate::Error>
339 + Send,
340 T: IntoHandled<Dispatch<Req, Notif, P>>,
341 ToFut: Fn(
342 &mut F,
343 Dispatch<Req, Notif, P>,
344 P::Connection<Counterpart>,
345 ) -> crate::BoxFuture<'_, Result<T, crate::Error>>
346 + Send
347 + Sync,
348{
349 fn describe_chain(&self) -> impl std::fmt::Debug {
350 format!(
351 "({}, {})",
352 std::any::type_name::<Req>(),
353 std::any::type_name::<Notif>()
354 )
355 }
356
357 async fn handle_dispatch_from(
358 &mut self,
359 dispatch: Dispatch,
360 connection: ConnectionTo<Counterpart>,
361 ) -> Result<Handled<Dispatch>, crate::Error> {
362 handle_incoming_dispatch(
363 self.counterpart.clone(),
364 self.peer.clone(),
365 dispatch,
366 connection,
367 async |dispatch, connection| match dispatch.into_typed_dispatch::<Req, Notif>()? {
368 Ok(typed_dispatch) => {
369 let result = (self.to_future_hack)(
370 &mut self.handler,
371 typed_dispatch.retag::<P>()?,
372 protocol::connection_from_raw::<P, _>(connection),
373 )
374 .await?;
375 match result.into_handled() {
376 Handled::Yes => Ok(Handled::Yes),
377 Handled::No {
378 message: Dispatch::Request(request, responder),
379 retry,
380 } => {
381 let untyped = request.to_untyped_message()?;
382 Ok(Handled::No {
383 message: Dispatch::Request(
384 untyped,
385 responder.erase_to_json().into_raw(),
386 ),
387 retry,
388 })
389 }
390 Handled::No {
391 message: Dispatch::Notification(notification),
392 retry,
393 } => {
394 let untyped = notification.to_untyped_message()?;
395 Ok(Handled::No {
396 message: Dispatch::Notification(untyped),
397 retry,
398 })
399 }
400 Handled::No {
401 message: Dispatch::Response(result, responder),
402 retry,
403 } => {
404 let method = responder.method();
405 let untyped_result = match result {
406 Ok(response) => response.into_json(method).map(Ok),
407 Err(err) => Ok(Err(err)),
408 }?;
409 Ok(Handled::No {
410 message: Dispatch::Response(
411 untyped_result,
412 responder.erase_to_json().into_raw(),
413 ),
414 retry,
415 })
416 }
417 }
418 }
419
420 Err(dispatch) => Ok(Handled::No {
421 message: dispatch,
422 retry: false,
423 }),
424 },
425 )
426 .await
427 }
428}
429
430pub struct NamedHandler<H> {
432 name: Option<String>,
433 handler: H,
434}
435
436impl<H> NamedHandler<H> {
437 pub fn new(name: Option<String>, handler: H) -> Self {
439 Self { name, handler }
440 }
441}
442
443impl<Counterpart: Role, H: HandleDispatchFrom<Counterpart>> HandleDispatchFrom<Counterpart>
444 for NamedHandler<H>
445{
446 fn describe_chain(&self) -> impl std::fmt::Debug {
447 format!(
448 "NamedHandler({:?}, {:?})",
449 self.name,
450 self.handler.describe_chain()
451 )
452 }
453
454 async fn handle_dispatch_from(
455 &mut self,
456 message: Dispatch,
457 connection: ConnectionTo<Counterpart>,
458 ) -> Result<Handled<Dispatch>, crate::Error> {
459 if let Some(name) = &self.name {
460 crate::util::instrumented_with_connection_name(
461 name.clone(),
462 self.handler.handle_dispatch_from(message, connection),
463 )
464 .await
465 } else {
466 self.handler.handle_dispatch_from(message, connection).await
467 }
468 }
469}
470
471pub struct ChainedHandler<H1, H2> {
473 handler1: H1,
474 handler2: H2,
475}
476
477impl<H1, H2> ChainedHandler<H1, H2> {
478 pub fn new(handler1: H1, handler2: H2) -> Self {
480 Self { handler1, handler2 }
481 }
482}
483
484#[inline(never)]
487fn boxed_dispatch<Counterpart, H>(
488 handler: &mut H,
489 message: Dispatch,
490 connection: ConnectionTo<Counterpart>,
491) -> crate::BoxFuture<'_, Result<Handled<Dispatch>, crate::Error>>
492where
493 Counterpart: Role,
494 H: HandleDispatchFrom<Counterpart>,
495{
496 Box::pin(handler.handle_dispatch_from(message, connection))
497}
498
499impl<Counterpart: Role, H1, H2> HandleDispatchFrom<Counterpart> for ChainedHandler<H1, H2>
500where
501 H1: HandleDispatchFrom<Counterpart>,
502 H2: HandleDispatchFrom<Counterpart>,
503{
504 fn describe_chain(&self) -> impl std::fmt::Debug {
505 format!(
506 "{:?}, {:?}",
507 self.handler1.describe_chain(),
508 self.handler2.describe_chain()
509 )
510 }
511
512 async fn handle_dispatch_from(
513 &mut self,
514 message: Dispatch,
515 connection: ConnectionTo<Counterpart>,
516 ) -> Result<Handled<Dispatch>, crate::Error> {
517 match boxed_dispatch(&mut self.handler1, message, connection.clone()).await? {
520 Handled::Yes => Ok(Handled::Yes),
521 Handled::No {
522 message,
523 retry: retry1,
524 } => match boxed_dispatch(&mut self.handler2, message, connection).await? {
525 Handled::Yes => Ok(Handled::Yes),
526 Handled::No {
527 message,
528 retry: retry2,
529 } => Ok(Handled::No {
530 message,
531 retry: retry1 | retry2,
532 }),
533 },
534 }
535 }
536}