@@ -56,6 +56,12 @@ impl PeerState {
56
56
pending_remove_webhook_requests : BoundedMap :: new ( MAX_PENDING_REQUESTS ) ,
57
57
}
58
58
}
59
+
60
+ fn is_empty ( & self ) -> bool {
61
+ self . pending_set_webhook_requests . is_empty ( )
62
+ && self . pending_list_webhooks_requests . is_empty ( )
63
+ && self . pending_remove_webhook_requests . is_empty ( )
64
+ }
59
65
}
60
66
61
67
/// Client-side handler for the LSPS5 (bLIP-55) webhook registration protocol.
@@ -345,8 +351,26 @@ where
345
351
}
346
352
} ;
347
353
self . with_peer_state ( * counterparty_node_id, handle_response) ;
354
+
355
+ self . check_and_remove_empty_peer_state ( counterparty_node_id) ;
356
+
348
357
result
349
358
}
359
+
360
+ fn check_and_remove_empty_peer_state ( & self , counterparty_node_id : & PublicKey ) {
361
+ let mut outer_state_lock = self . per_peer_state . write ( ) . unwrap ( ) ;
362
+ let should_remove =
363
+ if let Some ( peer_state_mutex) = outer_state_lock. get ( counterparty_node_id) {
364
+ let peer_state = peer_state_mutex. lock ( ) . unwrap ( ) ;
365
+ peer_state. is_empty ( )
366
+ } else {
367
+ false
368
+ } ;
369
+
370
+ if should_remove {
371
+ outer_state_lock. remove ( counterparty_node_id) ;
372
+ }
373
+ }
350
374
}
351
375
352
376
impl < ES : Deref > LSPSProtocolMessageHandler for LSPS5ClientHandler < ES >
@@ -461,36 +485,6 @@ mod tests {
461
485
}
462
486
}
463
487
464
- #[ test]
465
- fn test_handle_response_clears_pending_state ( ) {
466
- let ( client, _, _, peer, _) = setup_test_client ( ) ;
467
-
468
- let req_id = client
469
- . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
470
- . unwrap ( ) ;
471
-
472
- let response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
473
- num_webhooks : 1 ,
474
- max_webhooks : 5 ,
475
- no_change : false ,
476
- } ) ;
477
- let response_msg = LSPS5Message :: Response ( req_id. clone ( ) , response) ;
478
-
479
- {
480
- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
481
- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
482
- assert ! ( peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
483
- }
484
-
485
- client. handle_message ( response_msg, & peer) . unwrap ( ) ;
486
-
487
- {
488
- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
489
- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
490
- assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
491
- }
492
- }
493
-
494
488
#[ test]
495
489
fn test_unknown_request_id_handling ( ) {
496
490
let ( client, _message_queue, _, peer, _) = setup_test_client ( ) ;
@@ -552,4 +546,68 @@ mod tests {
552
546
assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
553
547
}
554
548
}
549
+
550
+ #[ test]
551
+ fn test_peer_state_cleanup_and_recreation ( ) {
552
+ let ( client, _, _, peer, _) = setup_test_client ( ) ;
553
+
554
+ let set_webhook_req_id = client
555
+ . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
556
+ . unwrap ( ) ;
557
+
558
+ let list_webhooks_req_id = client. list_webhooks ( peer) ;
559
+
560
+ {
561
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
562
+ assert ! ( state. contains_key( & peer) ) ;
563
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
564
+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
565
+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
566
+ }
567
+
568
+ let set_webhook_response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
569
+ num_webhooks : 1 ,
570
+ max_webhooks : 5 ,
571
+ no_change : false ,
572
+ } ) ;
573
+ let response_msg = LSPS5Message :: Response ( set_webhook_req_id. clone ( ) , set_webhook_response) ;
574
+ // trigger cleanup but there is still a pending request
575
+ // so the peer state should not be removed
576
+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
577
+
578
+ {
579
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
580
+ assert ! ( state. contains_key( & peer) ) ;
581
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
582
+ assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
583
+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
584
+ }
585
+
586
+ let list_webhooks_response =
587
+ LSPS5Response :: ListWebhooks ( crate :: lsps5:: msgs:: ListWebhooksResponse {
588
+ app_names : vec ! [ ] ,
589
+ max_webhooks : 5 ,
590
+ } ) ;
591
+ let response_msg = LSPS5Message :: Response ( list_webhooks_req_id, list_webhooks_response) ;
592
+
593
+ // now the pending request is handled, so the peer state should be removed
594
+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
595
+
596
+ {
597
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
598
+ assert ! ( !state. contains_key( & peer) ) ;
599
+ }
600
+
601
+ // check that it's possible to recreate the peer state by sending a new request
602
+ let new_req_id = client
603
+ . set_webhook ( peer, "test-app-2" . to_string ( ) , "https://example.com/hook2" . to_string ( ) )
604
+ . unwrap ( ) ;
605
+
606
+ {
607
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
608
+ assert ! ( state. contains_key( & peer) ) ;
609
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
610
+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
611
+ }
612
+ }
555
613
}
0 commit comments