|
78 | 78 | %% For AMQP management operations, we require a link pair as described in
|
79 | 79 | %% https://docs.oasis-open.org/amqp/linkpair/v1.0/cs01/linkpair-v1.0-cs01.html
|
80 | 80 | -record(management_link_pair, {
|
81 |
| - client_terminus_address :: tuple(), |
| 81 | + client_terminus_address, |
82 | 82 | incoming_half :: unattached | link_handle(),
|
83 | 83 | outgoing_half :: unattached | link_handle()
|
84 | 84 | }).
|
|
254 | 254 | queue_states = rabbit_queue_type:init() :: rabbit_queue_type:state()
|
255 | 255 | }).
|
256 | 256 |
|
| 257 | +-type state() :: #state{}. |
| 258 | + |
257 | 259 | start_link(ReaderPid, WriterPid, ChannelNum, FrameMax, User, Vhost, ConnName, BeginFrame) ->
|
258 | 260 | Args = {ReaderPid, WriterPid, ChannelNum, FrameMax, User, Vhost, ConnName, BeginFrame},
|
259 | 261 | Opts = [{hibernate_after, ?HIBERNATE_AFTER}],
|
@@ -1138,10 +1140,11 @@ handle_control(Detach = #'v1_0.detach'{handle = ?UINT(HandleInt)},
|
1138 | 1140 | {Unsettled1, _RemovedMsgIds} = remove_link_from_outgoing_unsettled_map(Ctag, Unsettled0),
|
1139 | 1141 | {QStates0, Unsettled1, OutgoingLinks0}
|
1140 | 1142 | end,
|
1141 |
| - State = State0#state{queue_states = QStates, |
1142 |
| - incoming_links = maps:remove(HandleInt, IncomingLinks), |
1143 |
| - outgoing_links = OutgoingLinks, |
1144 |
| - outgoing_unsettled_map = Unsettled}, |
| 1143 | + State1 = State0#state{queue_states = QStates, |
| 1144 | + incoming_links = maps:remove(HandleInt, IncomingLinks), |
| 1145 | + outgoing_links = OutgoingLinks, |
| 1146 | + outgoing_unsettled_map = Unsettled}, |
| 1147 | + State = maybe_detach_mgmt_link(HandleInt, State1), |
1145 | 1148 | maybe_detach_reply(Detach, State, State0),
|
1146 | 1149 | publisher_or_consumer_deleted(State, State0),
|
1147 | 1150 | {noreply, State};
|
@@ -2455,20 +2458,61 @@ publisher_or_consumer_deleted(
|
2455 | 2458 |
|
2456 | 2459 | %% If we previously already sent a detach with an error condition, and the Detach we
|
2457 | 2460 | %% receive here is therefore the client's reply, do not reply again with a 3rd detach.
|
2458 |
| -maybe_detach_reply(Detach, |
2459 |
| - #state{incoming_links = NewIncomingLinks, |
2460 |
| - outgoing_links = NewOutgoingLinks, |
2461 |
| - cfg = #cfg{writer_pid = WriterPid, |
2462 |
| - channel_num = Ch}}, |
2463 |
| - #state{incoming_links = OldIncomingLinks, |
2464 |
| - outgoing_links = OldOutgoingLinks}) |
| 2461 | +maybe_detach_reply( |
| 2462 | + Detach, |
| 2463 | + #state{incoming_links = NewIncomingLinks, |
| 2464 | + outgoing_links = NewOutgoingLinks, |
| 2465 | + incoming_management_links = NewIncomingMgmtLinks, |
| 2466 | + outgoing_management_links = NewOutgoingMgmtLinks, |
| 2467 | + cfg = #cfg{writer_pid = WriterPid, |
| 2468 | + channel_num = Ch}}, |
| 2469 | + #state{incoming_links = OldIncomingLinks, |
| 2470 | + outgoing_links = OldOutgoingLinks, |
| 2471 | + incoming_management_links = OldIncomingMgmtLinks, |
| 2472 | + outgoing_management_links = OldOutgoingMgmtLinks}) |
2465 | 2473 | when map_size(NewIncomingLinks) < map_size(OldIncomingLinks) orelse
|
2466 |
| - map_size(NewOutgoingLinks) < map_size(OldOutgoingLinks) -> |
| 2474 | + map_size(NewOutgoingLinks) < map_size(OldOutgoingLinks) orelse |
| 2475 | + map_size(NewIncomingMgmtLinks) < map_size(OldIncomingMgmtLinks) orelse |
| 2476 | + map_size(NewOutgoingMgmtLinks) < map_size(OldOutgoingMgmtLinks) -> |
2467 | 2477 | Reply = Detach#'v1_0.detach'{error = undefined},
|
2468 | 2478 | rabbit_amqp_writer:send_command(WriterPid, Ch, Reply);
|
2469 | 2479 | maybe_detach_reply(_, _, _) ->
|
2470 | 2480 | ok.
|
2471 | 2481 |
|
| 2482 | +-spec maybe_detach_mgmt_link(link_handle(), state()) -> state(). |
| 2483 | +maybe_detach_mgmt_link( |
| 2484 | + HandleInt, |
| 2485 | + State = #state{management_link_pairs = LinkPairs0, |
| 2486 | + incoming_management_links = IncomingLinks0, |
| 2487 | + outgoing_management_links = OutgoingLinks0}) -> |
| 2488 | + case maps:take(HandleInt, IncomingLinks0) of |
| 2489 | + {#management_link{name = Name}, IncomingLinks} -> |
| 2490 | + Pair = #management_link_pair{outgoing_half = OutgoingHalf} = maps:get(Name, LinkPairs0), |
| 2491 | + LinkPairs = case OutgoingHalf of |
| 2492 | + unattached -> |
| 2493 | + maps:remove(Name, LinkPairs0); |
| 2494 | + _ -> |
| 2495 | + maps:update(Name, Pair#management_link_pair{incoming_half = unattached}, LinkPairs0) |
| 2496 | + end, |
| 2497 | + State#state{incoming_management_links = IncomingLinks, |
| 2498 | + management_link_pairs = LinkPairs}; |
| 2499 | + error -> |
| 2500 | + case maps:take(HandleInt, OutgoingLinks0) of |
| 2501 | + {#management_link{name = Name}, OutgoingLinks} -> |
| 2502 | + Pair = #management_link_pair{incoming_half = IncomingHalf} = maps:get(Name, LinkPairs0), |
| 2503 | + LinkPairs = case IncomingHalf of |
| 2504 | + unattached -> |
| 2505 | + maps:remove(Name, LinkPairs0); |
| 2506 | + _ -> |
| 2507 | + maps:update(Name, Pair#management_link_pair{outgoing_half = unattached}, LinkPairs0) |
| 2508 | + end, |
| 2509 | + State#state{outgoing_management_links = OutgoingLinks, |
| 2510 | + management_link_pairs = LinkPairs}; |
| 2511 | + error -> |
| 2512 | + State |
| 2513 | + end |
| 2514 | + end. |
| 2515 | + |
2472 | 2516 | check_internal_exchange(#exchange{internal = true,
|
2473 | 2517 | name = XName}) ->
|
2474 | 2518 | protocol_error(?V_1_0_AMQP_ERROR_UNAUTHORIZED_ACCESS,
|
|
0 commit comments