diff --git a/src/amqp_network_connection.erl b/src/amqp_network_connection.erl index e5e98216..69fd71c8 100644 --- a/src/amqp_network_connection.erl +++ b/src/amqp_network_connection.erl @@ -26,6 +26,7 @@ -define(RABBIT_TCP_OPTS, [binary, {packet, 0}, {active,false}, {nodelay, true}]). -define(SOCKET_CLOSING_TIMEOUT, 1000). -define(HANDSHAKE_RECEIVE_TIMEOUT, 60000). +-define(TCP_MAX_PACKET_SIZE, (16#4000000 + ?EMPTY_FRAME_SIZE - 1)). -record(state, {sock, heartbeat, @@ -214,12 +215,21 @@ tune(#'connection.tune'{channel_max = ServerChannelMax, lists:max([Client, Server]); (Client, Server) -> lists:min([Client, Server]) - end, [ClientChannelMax, ClientHeartbeat, ClientFrameMax], - [ServerChannelMax, ServerHeartbeat, ServerFrameMax]), - NewState = State#state{heartbeat = Heartbeat, frame_max = FrameMax}, + end, + [ClientChannelMax, ClientHeartbeat, ClientFrameMax], + [ServerChannelMax, ServerHeartbeat, ServerFrameMax]), + %% If we attempt to recv > 64Mb, inet_drv will return enomem, so + %% we cap the max negotiated frame size accordingly. Note that + %% since we receive the frame header separately, we can actually + %% cope with frame sizes of 64M + ?EMPTY_FRAME_SIZE - 1. + CappedFrameMax = case FrameMax of + 0 -> ?TCP_MAX_PACKET_SIZE; + _ -> lists:min([FrameMax, ?TCP_MAX_PACKET_SIZE]) + end, + NewState = State#state{heartbeat = Heartbeat, frame_max = CappedFrameMax}, start_heartbeat(SHF, NewState), {#'connection.tune_ok'{channel_max = ChannelMax, - frame_max = FrameMax, + frame_max = CappedFrameMax, heartbeat = Heartbeat}, ChannelMax, NewState}. start_heartbeat(SHF, #state{sock = Sock, heartbeat = Heartbeat}) ->