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