127127-record (link ,
128128 {name :: link_name (),
129129 ref :: link_ref (),
130- state = detached :: detached | attach_sent | attached | detach_sent ,
130+ state = detached :: detached | attach_sent | attached | attach_refused | detach_sent ,
131131 notify :: pid (),
132132 output_handle :: output_handle (),
133133 input_handle :: input_handle () | undefined ,
@@ -325,9 +325,11 @@ mapped(cast, #'v1_0.end'{} = End, State) ->
325325 ok = notify_session_ended (End , State ),
326326 {stop , normal , State };
327327mapped (cast , # 'v1_0.attach' {name = {utf8 , Name },
328- initial_delivery_count = IDC ,
329328 handle = {uint , InHandle },
330329 role = PeerRoleBool ,
330+ source = Source ,
331+ target = Target ,
332+ initial_delivery_count = IDC ,
331333 max_message_size = MaybeMaxMessageSize } = Attach ,
332334 # state {links = Links , link_index = LinkIndex ,
333335 link_handle_index = LHI } = State0 ) ->
@@ -339,20 +341,28 @@ mapped(cast, #'v1_0.attach'{name = {utf8, Name},
339341 #{OutHandle := Link0 } = Links ,
340342 ok = notify_link_attached (Link0 , Attach , State0 ),
341343
342- {DeliveryCount , MaxMessageSize } =
344+ {LinkState , DeliveryCount , MaxMessageSize } =
343345 case Link0 of
344346 # link {role = sender = OurRole ,
345347 delivery_count = DC } ->
348+ LS = case Target of
349+ # 'v1_0.target' {} -> attached ;
350+ _ -> attach_refused
351+ end ,
346352 MSS = case MaybeMaxMessageSize of
347353 {ulong , S } when S > 0 -> S ;
348354 _ -> undefined
349355 end ,
350- {DC , MSS };
356+ {LS , DC , MSS };
351357 # link {role = receiver = OurRole ,
352358 max_message_size = MSS } ->
353- {unpack (IDC ), MSS }
359+ LS = case Source of
360+ # 'v1_0.source' {} -> attached ;
361+ _ -> attach_refused
362+ end ,
363+ {LS , unpack (IDC ), MSS }
354364 end ,
355- Link = Link0 # link {state = attached ,
365+ Link = Link0 # link {state = LinkState ,
356366 input_handle = InHandle ,
357367 delivery_count = DeliveryCount ,
358368 max_message_size = MaxMessageSize },
@@ -495,50 +505,41 @@ mapped({call, From},
495505 when Window =< 0 ->
496506 {keep_state_and_data , {reply , From , {error , remote_incoming_window_exceeded }}};
497507mapped ({call , From = {Pid , _ }},
498- {transfer , # 'v1_0.transfer' {handle = {uint , OutHandle },
499- delivery_tag = {binary , DeliveryTag },
500- settled = false } = Transfer0 , Sections },
501- # state {outgoing_delivery_id = DeliveryId , links = Links ,
502- outgoing_unsettled = Unsettled } = State ) ->
503- case Links of
504- #{OutHandle := # link {input_handle = undefined }} ->
505- {keep_state_and_data , {reply , From , {error , half_attached }}};
506- #{OutHandle := # link {link_credit = LC }} when LC =< 0 ->
507- {keep_state_and_data , {reply , From , {error , insufficient_credit }}};
508- #{OutHandle := Link = # link {max_message_size = MaxMessageSize ,
509- footer_opt = FooterOpt }} ->
510- Transfer = Transfer0 # 'v1_0.transfer' {delivery_id = uint (DeliveryId )},
511- case send_transfer (Transfer , Sections , FooterOpt , MaxMessageSize , State ) of
512- {ok , NumFrames } ->
513- State1 = State # state {outgoing_unsettled = Unsettled #{DeliveryId => {DeliveryTag , Pid }}},
514- {keep_state , book_transfer_send (NumFrames , Link , State1 ), {reply , From , ok }};
515- Error ->
516- {keep_state_and_data , {reply , From , Error }}
517- end ;
518- _ ->
519- {keep_state_and_data , {reply , From , {error , link_not_found }}}
520-
521- end ;
522- mapped ({call , From },
523- {transfer , # 'v1_0.transfer' {handle = {uint , OutHandle }} = Transfer0 ,
524- Sections }, # state {outgoing_delivery_id = DeliveryId ,
525- links = Links } = State ) ->
508+ {transfer ,
509+ # 'v1_0.transfer' {handle = {uint , OutHandle },
510+ delivery_tag = DeliveryTag ,
511+ settled = Settled } = Transfer0 ,
512+ Sections },
513+ # state {outgoing_delivery_id = DeliveryId ,
514+ links = Links ,
515+ outgoing_unsettled = Unsettled0 } = State0 ) ->
526516 case Links of
517+ #{OutHandle := # link {state = attach_refused }} ->
518+ {keep_state_and_data , {reply , From , {error , attach_refused }}};
527519 #{OutHandle := # link {input_handle = undefined }} ->
528520 {keep_state_and_data , {reply , From , {error , half_attached }}};
529521 #{OutHandle := # link {link_credit = LC }} when LC =< 0 ->
530522 {keep_state_and_data , {reply , From , {error , insufficient_credit }}};
531523 #{OutHandle := Link = # link {max_message_size = MaxMessageSize ,
532524 footer_opt = FooterOpt }} ->
533525 Transfer = Transfer0 # 'v1_0.transfer' {delivery_id = uint (DeliveryId )},
534- case send_transfer (Transfer , Sections , FooterOpt , MaxMessageSize , State ) of
526+ case send_transfer (Transfer , Sections , FooterOpt , MaxMessageSize , State0 ) of
535527 {ok , NumFrames } ->
528+ State = case Settled of
529+ true ->
530+ State0 ;
531+ false ->
532+ {binary , Tag } = DeliveryTag ,
533+ Unsettled = Unsettled0 #{DeliveryId => {Tag , Pid }},
534+ State0 # state {outgoing_unsettled = Unsettled }
535+ end ,
536536 {keep_state , book_transfer_send (NumFrames , Link , State ), {reply , From , ok }};
537537 Error ->
538538 {keep_state_and_data , {reply , From , Error }}
539539 end ;
540540 _ ->
541541 {keep_state_and_data , {reply , From , {error , link_not_found }}}
542+
542543 end ;
543544
544545mapped ({call , From },
@@ -688,21 +689,28 @@ send_flow_link(OutHandle,
688689 never -> never ;
689690 _ -> {RenewWhenBelow , Credit }
690691 end ,
691- #{OutHandle := # link {output_handle = H ,
692+ #{OutHandle := # link {state = LinkState ,
693+ output_handle = H ,
692694 role = receiver ,
693695 delivery_count = DeliveryCount ,
694696 available = Available } = Link } = Links ,
695- Flow1 = Flow0 # 'v1_0.flow' {
696- handle = uint (H ),
697- % % "In the event that the receiving link endpoint has not yet seen the
698- % % initial attach frame from the sender this field MUST NOT be set." [2.7.4]
699- delivery_count = maybe_uint (DeliveryCount ),
700- available = uint (Available )},
701- Flow = set_flow_session_fields (Flow1 , State ),
702- ok = send (Flow , State ),
703- State # state {links = Links #{OutHandle =>
704- Link # link {link_credit = Credit ,
705- auto_flow = AutoFlow }}}.
697+ case LinkState of
698+ attach_refused ->
699+ % % We will receive the DETACH frame shortly.
700+ State ;
701+ _ ->
702+ Flow1 = Flow0 # 'v1_0.flow' {
703+ handle = uint (H ),
704+ % % "In the event that the receiving link endpoint has not yet seen the
705+ % % initial attach frame from the sender this field MUST NOT be set." [2.7.4]
706+ delivery_count = maybe_uint (DeliveryCount ),
707+ available = uint (Available )},
708+ Flow = set_flow_session_fields (Flow1 , State ),
709+ ok = send (Flow , State ),
710+ State # state {links = Links #{OutHandle =>
711+ Link # link {link_credit = Credit ,
712+ auto_flow = AutoFlow }}}
713+ end .
706714
707715send_flow_session (State ) ->
708716 Flow = set_flow_session_fields (# 'v1_0.flow' {}, State ),
0 commit comments