summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2010-06-22 15:33:41 +0100
committerSimon MacMullen <simon@rabbitmq.com>2010-06-22 15:33:41 +0100
commita40971e3b11cd5a1b076ccfd4b2efc2400637f5c (patch)
treee9f3b73601606050fcb6e23400d91a36cd39e0aa
parent94952cd49e4da0ecba39db981e5db078dcb38b1d (diff)
downloadrabbitmq-server-a40971e3b11cd5a1b076ccfd4b2efc2400637f5c.tar.gz
Move frame_max handling from amqp_0_9_1 to soemthing branched from default.
-rw-r--r--src/rabbit_reader.erl34
-rw-r--r--src/rabbit_tests.erl40
2 files changed, 63 insertions, 11 deletions
diff --git a/src/rabbit_reader.erl b/src/rabbit_reader.erl
index 73a58f13..6cee27df 100644
--- a/src/rabbit_reader.erl
+++ b/src/rabbit_reader.erl
@@ -53,6 +53,9 @@
-define(CLOSING_TIMEOUT, 1).
-define(CHANNEL_TERMINATION_TIMEOUT, 3).
-define(SILENT_CLOSE_DELAY, 3).
+%% set to zero once QPid fix their negotiation
+-define(FRAME_MAX, 131072).
+-define(CHANNEL_MAX, 0).
%---------------------------------------------------------------------------
@@ -604,9 +607,8 @@ handle_method0(#'connection.start_ok'{mechanism = Mechanism,
User = rabbit_access_control:check_login(Mechanism, Response),
ok = send_on_channel0(
Sock,
- #'connection.tune'{channel_max = 0,
- %% set to zero once QPid fix their negotiation
- frame_max = 131072,
+ #'connection.tune'{channel_max = ?CHANNEL_MAX,
+ frame_max = ?FRAME_MAX,
heartbeat = 0}),
State#v1{connection_state = tuning,
connection = Connection#connection{
@@ -618,14 +620,24 @@ handle_method0(#'connection.tune_ok'{channel_max = _ChannelMax,
State = #v1{connection_state = tuning,
connection = Connection,
sock = Sock}) ->
- %% if we have a channel_max limit that the client wishes to
- %% exceed, die as per spec. Not currently a problem, so we ignore
- %% the client's channel_max parameter.
- rabbit_heartbeat:start_heartbeat(Sock, ClientHeartbeat),
- State#v1{connection_state = opening,
- connection = Connection#connection{
- timeout_sec = ClientHeartbeat,
- frame_max = FrameMax}};
+ if (FrameMax =< ?FRAME_MIN_SIZE) or
+ (?FRAME_MAX /= 0) and (FrameMax > ?FRAME_MAX) ->
+ rabbit_misc:protocol_error(
+ mistuned, "peer sent tune_ok with invalid frame_max", []);
+ %% If we have a channel_max limit that the client wishes to
+ %% exceed, die as per spec. Not currently a problem, so we ignore
+ %% the client's channel_max parameter.
+ %%(?CHANNEL_MAX /= 0) and (ChannelMax > ?CHANNEL_MAX) ->
+ %% rabbit_misc:protocol_error(
+ %% mistuned, "peer sent tune_ok with invalid channel_max");
+ true ->
+ rabbit_heartbeat:start_heartbeat(Sock, ClientHeartbeat),
+ State#v1{connection_state = opening,
+ connection = Connection#connection{
+ timeout_sec = ClientHeartbeat,
+ frame_max = FrameMax}}
+ end;
+
handle_method0(#'connection.open'{virtual_host = VHostPath,
insist = Insist},
State = #v1{connection_state = opening,
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index ecc2613d..a74beb99 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -55,6 +55,7 @@ all_tests() ->
passed = test_pg_local(),
passed = test_unfold(),
passed = test_parsing(),
+ passed = test_content_framing(),
passed = test_topic_matching(),
passed = test_log_management(),
passed = test_app_management(),
@@ -353,6 +354,45 @@ test_field_values() ->
>>),
passed.
+%% Test that content frames don't exceed frame-max
+test_content_framing(FrameMax, Fragments) ->
+ [Header | Frames] =
+ rabbit_binary_generator:build_simple_content_frames(
+ 1,
+ #content{class_id = 0, properties_bin = <<>>,
+ payload_fragments_rev = Fragments},
+ FrameMax),
+ % header is formatted correctly and the size is the total of the
+ % fragments
+ <<_FrameHeader:7/binary, _ClassAndWeight:4/binary,
+ BodySize:64/unsigned, _Rest/binary>> = list_to_binary(Header),
+ BodySize = size(list_to_binary(Fragments)),
+ false = lists:any(
+ fun (ContentFrame) ->
+ FrameBinary = list_to_binary(ContentFrame),
+ % assert
+ <<_TypeAndChannel:3/binary,
+ Size:32/unsigned,
+ _Payload:Size/binary,
+ 16#CE>> = FrameBinary,
+ size(FrameBinary) > FrameMax
+ end,
+ Frames),
+ passed.
+
+test_content_framing() ->
+ % no content
+ passed = test_content_framing(4096, []),
+ passed = test_content_framing(4096, [<<>>]),
+ % easily fit in one frame
+ passed = test_content_framing(4096, [<<"Easy">>]),
+ % exactly one frame (empty frame = 8 bytes)
+ passed = test_content_framing(11, [<<"One">>]),
+ % more than one frame
+ passed = test_content_framing(20, [<<"into more than one frame">>,
+ <<"This will have to go">>]),
+ passed.
+
test_topic_match(P, R) ->
test_topic_match(P, R, true).