Closed minghuaw closed 1 year ago
@xinchen10, @vinaysurya :
The client pattern appears in the Microsoft.Azure.ServiceBus
receiver and carried forward to the current generation. I don't have access to confirm what was used in the T0 package, but I suspect that it also builds its filter set the same way.
My assumption from the historical client patterns is that AmqpCodec held responsibility for encoding the map and is translating to symbol/described as needed for spec compliance. However, based on @minghuaw's findings, that does not appear to be the case.
We know that the session filter is being applied and the client features work correctly, so it does not appear that we have a functional problem. However, I'm not sure if:
AmqpCodec
or the client should be translating to symbol/described when setting the filterWould appreciate thoughts from Xin and Vinay on whether the client pattern should be adjusted, or you'd advise leaving as-is.
//fyi: @JoshLove-msft
@minghuaw Please use the following to send a session-filter to the SB service.
<type name="com.microsoft:session-filter" class="restricted" source="string" provides="filter">
<descriptor name="com.microsoft:session-filter" code="0x00000137:000000C"/>
</type>
The service supports a described string as the session-id. The plain string is a legacy from the AMQP protocol development time. The SDK started with that and was not updated later.
It would be nice to require or enforce described types in FilterSet but we will consider that in the future. For now the user is responsible for putting a correct type in the set.
Thanks a lot!
@xinchen10 FYI, it seems like only the descriptor name works for now. An error (shown below) is returned if the descriptor code is sent
invalid filter type. System only support Jms or Apache selector filter type but we found type 'Microsoft.ServiceBus.Messaging.Amqp.Encoding.DescribedType' associated with key 'com.microsoft:session-filter'
@minghuaw is the descriptor code encoded as ulong?
@xinchen10 Thanks for your quick response.
@minghuaw is the descriptor code encoded as ulong?
It is. I will paste the serialized bytes of a SessionFilter("test".to_string())
below.
0x0, 0x80, 0x0, 0x0, 0x1, 0x37, 0x0, 0x0, 0x0, 0xc, 0xa1, 0x4, 0x74, 0x65, 0x73, 0x74
0x0, 0xa3, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
0x66, 0x74, 0x3a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x66, 0x69, 0x6c,
0x74, 0x65, 0x72, 0xa1, 0x4, 0x74, 0x65, 0x73, 0x74
I found the problem. The provided descriptor code is not strictly compliant to the spec.
0x00000137:000000C
is actually interpreted as 0x0000_0013_7000_000C
. However, this is not strictly compliant to the protocol, according to the protocol (http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#section-descriptor-values),
numeric descriptors: (domain-id << 32) | descriptor-id
A strictly-compliant descriptor code should be 0x0000_0137 << 32 | 0x000_000c
, but the actual descriptor code is 0x0000_0013 << 32 | 0x7000_000c
.
I guess this is fine as the types won't be used outside Service Bus or other microsoft products. I am re-opening this issue simply to see whether this will be changed in the service itself to be strictly compliant or not. Thanks in advance :)
I am pretty sure the ulong code was intended to be 0x0000_0137 << 32 | 0x000_000c
and the current working one is probably a typo. It is not easy to fix the existing clients but I will notify the service team to add support for the correct codes on the service side.
Problem
The way a
ServiceBusSessionReceiver
is created inAzure.Messaging.ServiceBus
sdk is not compliant with the AMQP 1.0 protocol. Currently, the way it is implemented inAzure.Messaging.ServiceBus
is like following (Line 681)where
filters
is aFilterSet
andsessionId
is just astring
. ThesessionId
is added as one entry to thefilter-set
field of the receiver link'sSource
However, regarding the
filter-set
type, the AMQP 1.0 core spec states that (http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-filter-set)The
FilterSet
type is defined as aRestrictedMap<AmqpSymbol>
that only restricts the type of key but leaves the value type asobject
. This leaves the room for the user to mistakenly use the library in a way that is not compliant with the protocol.Related issue
Another issue has been opened in the Azure/azure-sdk-for-net repo. Azure/azure-sdk-for-net#32243
Further Investigation
To confirm that the
string
value in thefilter-set
is not actually serialized as a "described type" on the wire, I have created an minimal example with Azure/azure-amqp, where the receiver link is created similarly withthefilter-set
field set to contain an entry of astring
And I captured the bytes with wireshark and found out that it is NOT compliant to the AMQP protocol.
I am going to open an issue on Azure/azure-amqp, but for the sake of completeness, I will paste the captured bytes and explain why it is not compliant below
The captured bytes for the receiver link's
Attach
frame are:And the part that we are interested in is the
FilterSet
part of theSource
field, which contains the following bytesBreaking down the captured bytes, the
FilterSet
field is a map as indicated by the format codec1
at the beginning. And it contains only one key and one value.Symbol
in the map (as indicated by the format codea3
). The key, if converted to ASCII (starting from63
), literally translates tocom.microsoft:session-filter
a1
) that immediately follows the keyAnd this is where it doesn't comply with the AMQP 1.0 protocol. As mentioned previously, the
filter-set
type is defined asAnd on the wire, a described type should start with
0x00
and look like the Figure 1.2 (http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#doc-idp38080), which is pasted below. The value bytes pasted above clearly doesn't look anything close to a "described type"