@@ -200,17 +200,36 @@ pub enum SendError {
200200///
201201/// [`IgnoringMessageHandler`]: crate::ln::peer_handler::IgnoringMessageHandler
202202/// [`CustomMessage`]: Self::CustomMessage
203- pub trait CustomOnionMessageHandler {
203+ pub trait CustomOnionMessageHandler : ResponseErrorHandler {
204204 /// The message known to the handler. To support multiple message types, you may want to make this
205205 /// an enum with a variant for each supported message.
206206 type CustomMessage : CustomOnionMessageContents ;
207- /// Called with the custom message that was received.
208- fn handle_custom_message ( & self , msg : Self :: CustomMessage ) ;
207+
208+ /// Called with the custom message that was received, returning a response to send, if any.
209+ fn handle_custom_message ( & self , msg : Self :: CustomMessage ) -> Option < Self :: CustomMessage > ;
210+
209211 /// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
210212 /// message type is unknown.
211213 fn read_custom_message < R : io:: Read > ( & self , message_type : u64 , buffer : & mut R ) -> Result < Option < Self :: CustomMessage > , msgs:: DecodeError > ;
212214}
213215
216+ ///
217+ pub trait ResponseErrorHandler {
218+ /// Called if an error occurred when sending a response to the handled message.
219+ fn handle_response_error ( & self , error : ResponseError ) ;
220+ }
221+
222+ ///
223+ #[ derive( Debug , PartialEq , Eq ) ]
224+ pub enum ResponseError {
225+ ///
226+ GetNodeIdFailed ,
227+ ///
228+ NoReplyPath ,
229+ ///
230+ Sending ( SendError ) ,
231+ }
232+
214233impl < ES : Deref , NS : Deref , L : Deref , MR : Deref , OMH : Deref , CMH : Deref >
215234OnionMessenger < ES , NS , L , MR , OMH , CMH >
216235where
@@ -295,6 +314,45 @@ where
295314 }
296315 }
297316
317+ fn respond_with_onion_message < T : CustomOnionMessageContents , EH : ResponseErrorHandler > (
318+ & self , response : OnionMessageContents < T > , path_id : Option < [ u8 ; 32 ] > ,
319+ reply_path : Option < BlindedPath > , error_handler : & EH
320+ ) {
321+ let sender = match self . node_signer . get_node_id ( Recipient :: Node ) {
322+ Ok ( node_id) => node_id,
323+ Err ( _) => {
324+ log_info ! (
325+ self . logger, "No sender to respond to onion message with path_id {:02x?}" ,
326+ path_id
327+ ) ;
328+ return error_handler. handle_response_error ( ResponseError :: GetNodeIdFailed ) ;
329+ }
330+ } ;
331+
332+ let destination = match reply_path {
333+ Some ( reply_path) => Destination :: BlindedPath ( reply_path) ,
334+ None => {
335+ log_info ! (
336+ self . logger, "No reply path to respond to onion message with path_id {:02x?}" ,
337+ path_id
338+ ) ;
339+ return error_handler. handle_response_error ( ResponseError :: NoReplyPath ) ;
340+ } ,
341+ } ;
342+
343+ let intermediate_nodes = self . message_router . find_route ( & sender, & destination) ;
344+
345+ log_info ! ( self . logger, "Responding to onion message with path_id {:02x?}" , path_id) ;
346+
347+ if let Err ( e) = self . send_onion_message ( & intermediate_nodes, destination, response, None ) {
348+ log_info ! (
349+ self . logger, "Failed responding to onion message with path_id {:02x?}: {:?}" ,
350+ path_id, e
351+ ) ;
352+ return error_handler. handle_response_error ( ResponseError :: Sending ( e) ) ;
353+ }
354+ }
355+
298356 #[ cfg( test) ]
299357 pub ( super ) fn release_pending_msgs ( & self ) -> HashMap < PublicKey , VecDeque < msgs:: OnionMessage > > {
300358 let mut pending_msgs = self . pending_messages . lock ( ) . unwrap ( ) ;
@@ -338,7 +396,7 @@ where
338396 NS :: Target : NodeSigner ,
339397 L :: Target : Logger ,
340398 MR :: Target : MessageRouter ,
341- OMH :: Target : OffersMessageHandler ,
399+ OMH :: Target : OffersMessageHandler + Sized ,
342400 CMH :: Target : CustomOnionMessageHandler + Sized ,
343401{
344402 /// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
@@ -377,9 +435,27 @@ where
377435 log_info!( self . logger,
378436 "Received an onion message with path_id {:02x?} and {} reply_path" ,
379437 path_id, if reply_path. is_some ( ) { "a" } else { "no" } ) ;
380- match message {
381- OnionMessageContents :: Offers ( msg) => self . offers_handler . handle_message ( msg) ,
382- OnionMessageContents :: Custom ( msg) => self . custom_handler . handle_custom_message ( msg) ,
438+
439+ let response = match message {
440+ OnionMessageContents :: Offers ( msg) => {
441+ self . offers_handler . handle_message ( msg)
442+ . map ( |msg| OnionMessageContents :: Offers ( msg) )
443+ } ,
444+ OnionMessageContents :: Custom ( msg) => {
445+ self . custom_handler . handle_custom_message ( msg)
446+ . map ( |msg| OnionMessageContents :: Custom ( msg) )
447+ } ,
448+ } ;
449+
450+ if let Some ( response) = response {
451+ match response {
452+ OnionMessageContents : : Offers ( _) => self . respond_with_onion_message (
453+ response, path_id, reply_path, & * self . offers_handler
454+ ) ,
455+ OnionMessageContents : : Custom ( _) => self . respond_with_onion_message (
456+ response, path_id, reply_path, & * self . custom_handler
457+ ) ,
458+ }
383459 }
384460 } ,
385461 Ok ( ( Payload :: Forward ( ForwardControlTlvs :: Unblinded ( ForwardTlvs {
0 commit comments