Skip to content

Protocol violation when sending FLOW #575

@ansd

Description

@ansd

AMQP 1.0 section 2.7.4 states for FLOW field next-incoming-id:

This value MUST be set if the peer has received the begin frame for the session, and MUST NOT be set if it has not.

However, this client always sets field next-incoming-id irrespective whether it has received the server's BEGIN frame.

Reproduction steps:

In root folder of https://github.com/ansd/rabbitmq-server/tree/native-amqp-dotnet-bug, run

make -C deps/rabbitmq_amqp1_0 ct-system t=dotnet:redelivery

The test case fails with error

Amqp.AmqpException: next-incoming-id from FLOW (0) leads next-outgoing-id (4294967292)

Here is an easier example:
Start latest RabbitMQ server https://github.com/rabbitmq/rabbitmq-server/tree/v3.12.8 (probably any other server will do it as well):

make run-broker PLUGINS="rabbitmq_amqp1_0 rabbitmq_management"

Create a C# project:

dotnet new console

Modify the .csproj file to contain

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <RootNamespace>rabbit_dot_net</RootNamespace>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="AmqpNetLite" Version="2.4.7" />
    </ItemGroup>
</Project>

and the Program.cs file to contain

using Amqp;

Trace.TraceLevel = TraceLevel.Frame;
Trace.TraceListener = (l, f, a) => Console.WriteLine(DateTime.Now.ToString("[hh:mm:ss.fff]") + " " + string.Format(f, a));

Address address = new Address("amqp://guest:guest@localhost:5672");
Connection connection = new Connection(address);
Session session = new Session(connection);

ReceiverLink receiver = new ReceiverLink(session, "receiver-link", "q1");
Message response = receiver.Receive();

Start the client:

dotnet run
[05:08:26.761] SEND AMQP 3 1 0 0
[05:08:26.804] RECV sasl-mechanisms(sasl-server-mechanisms:[ANONYMOUS,PLAIN,AMQPLAIN])
[05:08:26.806] SEND sasl-init(mechanism:PLAIN,initial-response:...,hostname:localhost)
[05:08:26.807] RECV sasl-outcome(code:Ok)
[05:08:26.808] SEND AMQP 0 1.0.0
[05:08:26.809] SEND (ch=0) open(container-id:AMQPNetLite-7ec36d4f,host-name:localhost,max-frame-size:262144,channel-max:255,idle-time-out:1073741823)
[05:08:26.809] RECV AMQP 0 1 0 0
[05:08:26.810] SEND (ch=0) begin(next-outgoing-id:4294967293,incoming-window:2048,outgoing-window:2048,handle-max:1023)
[05:08:26.811] SEND (ch=0) attach(name:receiver-link,handle:0,role:True,source:source(address:q1),target:target())
[05:08:26.812] SEND (ch=0) flow(next-in-id:0,in-window:2048,next-out-id:4294967293,out-window:2048,handle:0,delivery-count:0,link-credit:200,drain:False)
[05:08:26.815] RECV (ch=0) open(container-id:rabbit@myhost,max-frame-size:262144,channel-max:255,idle-time-out:60000,properties:[cluster_name:rabbit@myhost,copyright:Copyright (c) 2007-2023 VMware, Inc. or its affiliates.,information:Licensed under the MPL 2.0. Website: https://rabbitmq.com,platform:Erlang/OTP 26.1.2,product:RabbitMQ,version:3.12.8])
[05:08:26.818] RECV (ch=0) begin(remote-channel:0,next-outgoing-id:0,incoming-window:65535,outgoing-window:65535,handle-max:1023)
[05:08:26.819] RECV (ch=0) attach(name:receiver-link,handle:0,role:False,snd-settle-mode:Unsettled,source:source(address:q1,default-outcome:released(),outcomes:[amqp:accepted:list,amqp:rejected:list,amqp:released:list,amqp:modified:list]),initial-delivery-count:0)
[05:08:26.820] RECV (ch=0) flow(next-in-id:4294967293,in-window:65535,next-out-id:0,out-window:65535,handle:0,delivery-count:0,link-credit:200,available:0,drain:False)

As seen in the trace output, the client sends flow(next-in-id:0 before it receives the begin.
Instead of setting next-in-id to 0, the correct behaviour is to not set that field.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions