Skip to content

Commit 6b24e3d

Browse files
committed
Validate that link handle is not in use
"The handle MUST NOT be used for other open links. An attempt to attach using a handle which is already associated with a link MUST be responded to with an immediate close carrying a handle-in-use session-error." (cherry picked from commit 4b59c19)
1 parent 124899f commit 6b24e3d

2 files changed

Lines changed: 55 additions & 9 deletions

File tree

deps/rabbit/src/rabbit_amqp_session.erl

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,13 +1211,14 @@ handle_frame(#'v1_0.attach'{handle = ?UINT(Handle)},
12111211
"link handle value (~b) exceeds maximum link handle value (~b)",
12121212
[Handle, MaxHandle]);
12131213
handle_frame(#'v1_0.attach'{name = {utf8, NameBin} = Name,
1214-
handle = Handle,
1214+
handle = ?UINT(HandleInt) = Handle,
12151215
role = Role,
12161216
source = Source,
12171217
target = Target,
12181218
snd_settle_mode = SndSettleMode,
12191219
rcv_settle_mode = RcvSettleMode} = Attach,
12201220
State) ->
1221+
ok = validate_handle_not_in_use(HandleInt, State),
12211222
try
12221223
ok = validate_attach(Attach),
12231224
handle_attach(Attach, State)
@@ -1506,10 +1507,6 @@ handle_attach(#'v1_0.attach'{role = ?AMQP_ROLE_SENDER,
15061507
Flow = #'v1_0.flow'{handle = Handle,
15071508
delivery_count = DeliveryCount,
15081509
link_credit = ?UINT(MaxLinkCredit)},
1509-
%%TODO check that handle is not in use for any other open links.
1510-
%%"The handle MUST NOT be used for other open links. An attempt to attach
1511-
%% using a handle which is already associated with a link MUST be responded to
1512-
%% with an immediate close carrying a handle-in-use session-error."
15131510
IncomingLinks = IncomingLinks0#{HandleInt => IncomingLink},
15141511
State = State0#state{incoming_links = IncomingLinks,
15151512
permission_cache = PermCache},
@@ -3424,14 +3421,30 @@ validate_attach(#'v1_0.attach'{unsettled = {map, [_|_]}}) ->
34243421
exit_not_implemented("Link recovery not supported");
34253422
validate_attach(#'v1_0.attach'{incomplete_unsettled = true}) ->
34263423
exit_not_implemented("Link recovery not supported");
3427-
validate_attach(
3428-
#'v1_0.attach'{snd_settle_mode = SndSettleMode,
3429-
rcv_settle_mode = ?V_1_0_RECEIVER_SETTLE_MODE_SECOND})
3424+
validate_attach(#'v1_0.attach'{snd_settle_mode = SndSettleMode,
3425+
rcv_settle_mode = ?V_1_0_RECEIVER_SETTLE_MODE_SECOND})
34303426
when SndSettleMode =/= ?V_1_0_SENDER_SETTLE_MODE_SETTLED ->
34313427
exit_not_implemented("rcv-settle-mode second not supported");
34323428
validate_attach(#'v1_0.attach'{}) ->
34333429
ok.
34343430

3431+
%% "The handle MUST NOT be used for other open links. An attempt to attach
3432+
%% using a handle which is already associated with a link MUST be responded
3433+
%% to with an immediate close carrying a handle-in-use session-error." [2.7.3]
3434+
validate_handle_not_in_use(Handle, #state{incoming_links = IL,
3435+
outgoing_links = OL,
3436+
incoming_management_links = IML,
3437+
outgoing_management_links = OML})
3438+
when is_map_key(Handle, IL) orelse
3439+
is_map_key(Handle, OL) orelse
3440+
is_map_key(Handle, IML) orelse
3441+
is_map_key(Handle, OML) ->
3442+
protocol_error(?V_1_0_SESSION_ERROR_HANDLE_IN_USE,
3443+
"handle ~b is already associated with a link",
3444+
[Handle]);
3445+
validate_handle_not_in_use(_, _) ->
3446+
ok.
3447+
34353448
validate_multi_transfer_delivery_id(?UINT(Id), Id) ->
34363449
ok;
34373450
validate_multi_transfer_delivery_id(undefined, _FirstDeliveryId) ->

deps/rabbit/test/amqp_client_SUITE.erl

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ groups() ->
184184
bad_x_cc_annotation_exchange,
185185
decimal_types,
186186
consumer_timeout_quorum_queue_policy,
187-
consumer_timeout_quorum_queue_consumer_arg
187+
consumer_timeout_quorum_queue_consumer_arg,
188+
handle_in_use
188189
]},
189190

190191
{cluster_size_3, [shuffle],
@@ -5343,6 +5344,38 @@ attach_to_exclusive_queue(Config) ->
53435344
#'queue.delete_ok'{} = amqp_channel:call(Ch, #'queue.delete'{queue = QName}),
53445345
ok = rabbit_ct_client_helpers:close_connection_and_channel(Conn, Ch).
53455346

5347+
%% "The handle MUST NOT be used for other open links. An attempt to attach
5348+
%% using a handle which is already associated with a link MUST be responded
5349+
%% to with an immediate close carrying a handle-in-use session-error." [2.7.3]
5350+
handle_in_use(Config) ->
5351+
OpnConf = connection_config(Config),
5352+
{ok, Connection} = amqp10_client:open_connection(OpnConf),
5353+
{ok, Session} = amqp10_client:begin_session_sync(Connection),
5354+
Address = rabbitmq_amqp_address:exchange(<<"amq.direct">>, <<"my key">>),
5355+
5356+
Handle = 99,
5357+
SenderArgs1 = #{name => <<"sender-1">>,
5358+
role => {sender, #{address => Address}},
5359+
snd_settle_mode => mixed,
5360+
rcv_settle_mode => first,
5361+
handle => Handle},
5362+
{ok, Sender1} = amqp10_client:attach_link(Session, SenderArgs1),
5363+
ok = wait_for_credit(Sender1),
5364+
5365+
%% Attaching another link with the same handle should close the session.
5366+
SenderArgs2 = SenderArgs1#{name := <<"sender-2">>},
5367+
{ok, _Sender2} = amqp10_client:attach_link(Session, SenderArgs2),
5368+
receive {amqp10_event,
5369+
{session, Session,
5370+
{ended,
5371+
#'v1_0.error'{
5372+
condition = ?V_1_0_SESSION_ERROR_HANDLE_IN_USE,
5373+
description = {utf8, <<"handle 99 is already associated with a link">>}
5374+
}}}} -> ok
5375+
after 9000 -> ct:fail({missing_event, ?LINE})
5376+
end,
5377+
ok = close_connection_sync(Connection).
5378+
53465379
dynamic_target_short_link_name(Config) ->
53475380
OpnConf0 = connection_config(Config),
53485381
OpnConf = OpnConf0#{container_id := <<"my-container">>,

0 commit comments

Comments
 (0)