diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2010-06-22 15:33:41 +0100 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2010-06-22 15:33:41 +0100 |
commit | a40971e3b11cd5a1b076ccfd4b2efc2400637f5c (patch) | |
tree | e9f3b73601606050fcb6e23400d91a36cd39e0aa | |
parent | 94952cd49e4da0ecba39db981e5db078dcb38b1d (diff) | |
download | rabbitmq-server-a40971e3b11cd5a1b076ccfd4b2efc2400637f5c.tar.gz |
Move frame_max handling from amqp_0_9_1 to soemthing branched from default.
-rw-r--r-- | src/rabbit_reader.erl | 34 | ||||
-rw-r--r-- | src/rabbit_tests.erl | 40 |
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). |