@@ -369,3 +369,109 @@ async fn test_make_request_preserves_remote_target_and_route_order() -> crate::R
369369
370370 Ok ( ( ) )
371371}
372+
373+ #[ tokio:: test]
374+ async fn test_route_set_updates_from_200_ok_response ( ) -> crate :: Result < ( ) > {
375+ let endpoint = create_test_endpoint ( ) . await ?;
376+ let ( state_sender, _) = unbounded_channel ( ) ;
377+
378+ let dialog_id = DialogId {
379+ call_id : "route-update-call" . to_string ( ) ,
380+ from_tag : "from-tag" . to_string ( ) ,
381+ to_tag : "" . to_string ( ) ,
382+ } ;
383+
384+ let invite_req = create_invite_request ( "from-tag" , "" , "route-update-call" ) ;
385+ let ( tu_sender, _tu_receiver) = unbounded_channel ( ) ;
386+
387+ let dialog_inner = DialogInner :: new (
388+ TransactionRole :: Client ,
389+ dialog_id,
390+ invite_req,
391+ endpoint. inner . clone ( ) ,
392+ state_sender,
393+ None ,
394+ Some ( Uri :: try_from ( "sip:alice@alice.example.com:5060" ) ?) ,
395+ tu_sender,
396+ ) ?;
397+
398+ let client_dialog = ClientInviteDialog {
399+ inner : Arc :: new ( dialog_inner) ,
400+ } ;
401+
402+ let remote_target = Uri :: try_from ( "sip:uas@192.0.2.55:5088;transport=tcp" ) ?;
403+ client_dialog
404+ . inner
405+ . set_remote_target ( remote_target. clone ( ) , None ) ;
406+
407+ let mut headers: Vec < Header > = vec ! [
408+ Via :: new( "SIP/2.0/TCP proxy.example.com:5060;branch=z9hG4bKproxy" ) . into( ) ,
409+ CSeq :: new( "1 INVITE" ) . into( ) ,
410+ From :: new( "Alice <sip:alice@example.com>;tag=from-tag" ) . into( ) ,
411+ To :: new( "Bob <sip:bob@example.com>;tag=bob-tag" ) . into( ) ,
412+ CallId :: new( "route-update-call" ) . into( ) ,
413+ Header :: RecordRoute ( RecordRoute :: new(
414+ "<sip:edge1.example.net:5070;transport=tcp;lr>" ,
415+ ) ) ,
416+ Header :: RecordRoute ( RecordRoute :: new(
417+ "<sip:edge2.example.net:5080;transport=tcp;lr>" ,
418+ ) ) ,
419+ ] ;
420+ headers. push ( ContentLength :: new ( "0" ) . into ( ) ) ;
421+
422+ let success_resp = Response {
423+ status_code : StatusCode :: OK ,
424+ version : rsip:: Version :: V2 ,
425+ headers : headers. into ( ) ,
426+ body : vec ! [ ] ,
427+ } ;
428+
429+ client_dialog
430+ . inner
431+ . update_route_set_from_response ( & success_resp) ;
432+
433+ let outbound_addr =
434+ SipAddr :: try_from ( & Uri :: try_from ( "sip:uac.example.com:5060;transport=tcp" ) ?) ?;
435+ let bye_request = client_dialog. inner . make_request (
436+ rsip:: Method :: Bye ,
437+ None ,
438+ Some ( outbound_addr) ,
439+ None ,
440+ None ,
441+ None ,
442+ ) ?;
443+
444+ let routes: Vec < String > = bye_request
445+ . headers
446+ . iter ( )
447+ . filter_map ( |header| match header {
448+ Header :: Route ( route) => Some ( route. value ( ) . to_string ( ) ) ,
449+ _ => None ,
450+ } )
451+ . collect ( ) ;
452+
453+ assert_eq ! (
454+ routes,
455+ vec![
456+ "<sip:edge2.example.net:5080;transport=tcp;lr>" . to_string( ) ,
457+ "<sip:edge1.example.net:5070;transport=tcp;lr>" . to_string( ) ,
458+ ] ,
459+ "Route set must be reversed compared to the Record-Route header order" ,
460+ ) ;
461+
462+ let destination = destination_from_request ( & bye_request)
463+ . expect ( "route-enabled request should resolve to a destination" ) ;
464+ let expected_destination =
465+ SipAddr :: try_from ( & Uri :: try_from ( "sip:edge2.example.net:5080;transport=tcp" ) ?) ?;
466+ assert_eq ! (
467+ destination, expected_destination,
468+ "First Route entry must determine the transport destination" ,
469+ ) ;
470+
471+ assert_eq ! (
472+ bye_request. uri, remote_target,
473+ "Record-Route application must not change the remote target" ,
474+ ) ;
475+
476+ Ok ( ( ) )
477+ }
0 commit comments