Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty Response to a Read operation #579

Open
dnav opened this issue Jun 10, 2024 · 22 comments
Open

Empty Response to a Read operation #579

dnav opened this issue Jun 10, 2024 · 22 comments

Comments

@dnav
Copy link
Member

dnav commented Jun 10, 2024

  • Name, version and date of the document:
    • OMA-TS-LightweightM2M_Transport-V1_2_1-20221209-A.pdf
    • OMA-TS-LightweightM2M_Transport-V1_1_1-20190617-A.pdf
    • OMA-TS-LightweightM2M-V1_0_2-20180209-A.pdf

The response to a Read operation may be empty: An Object Instance may have no readable Resource, or a Resource may not have any Resource Instance. The TS indicates that in this case, the response code is 2.05 Content and there is no attached payload since there are no values to report:

Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object
Instance. In this case the response code is still 2.05 Content.

We recently faced an interoperability issue using the CoAP binding. In such a case, should the CoAP response include a Content-Format option or not?

@sbernard31
Copy link

In LWM2M in addition of the sentence you share I found about that it :

Messages containing data MUST specify the payload encoding by using one of the supported data formats.

(In Data Formats for Transferring Resource Information in LWM2M v1.0.2, 1.1.1, 1.2.1)

I looked at CoAP RFC and only found :

5.9.1.5. 2.05 Content

This Response Code is like HTTP 200 "OK" but only used in response to
GET requests.

The payload returned with the response is a representation of the
target resource.

This response is cacheable: Caches can use the Max-Age Option to
determine freshness (see Section 5.6.1) and (if present) the ETag
Option for validation (see Section 5.6.2).

5.10.3. Content-Format

The Content-Format Option indicates the representation format of the
message payload. The representation format is given as a numeric
Content-Format identifier that is defined in the "CoAP Content-
Formats" registry (Section 12.3). In the absence of the option, no
default value is assumed, i.e., the representation format of any
representation message payload is indeterminate (Section 5.5).

So I guess this depends a lot if you consider your response contains "no payload" or an "empty payload" which is the result of chosen encoding format.

From my point of view, a 2.05 response is "a representation of the target resource" (like explained in CoAP RFC) in a given content format. Sometime this lead to empty byte[] or empty string but this is still the result of a given encoding format.
If that case, I think content format should be used (even if the payload is empty).

I checked how behave Leshan and it reject 2.05 response without content format and it does not always encode "no lwm2m node" with an empty payload. (e.g. for SenML it returns an empty array "[]")

@sbernard31
Copy link

We recently faced an interoperability issue using the CoAP binding. In such a case, should the CoAP response include a Content-Format option or not?

What was the interoperability issue exactly ?

@dnav
Copy link
Member Author

dnav commented Jun 10, 2024

What was the interoperability issue exactly ?

It just so happens that a Leshan-based Server is returning an error "Invalid Response: Unable to decode response payload" when receiving a CoAP response with no payload and no Content-format option ;)

And in some cases, it also fails even if a content-format is present.

@sbernard31
Copy link

sbernard31 commented Jun 10, 2024

It just so happens that a Leshan-based Server is returning an error "Invalid Response: Unable to decode response payload" when receiving a CoAP response with no payload and no Content-format option ;)

😅 OK so now you get the reason (#579 (comment))

Technically we get the decoder from given content format. (We have 1 decoder by content format)
Then we provide the payload to it to decode payload.
If we have no content format we are not able to select decoder and we raise an error.

But if OMA clarifies that I guess we can adapt Leshan code.

And in some cases, it also fails even if a content-format is present.

This one is maybe a bug ? do you have more details ? (maybe we should continue that point in a Leshan issue ?)

@dnav
Copy link
Member Author

dnav commented Jun 11, 2024

This one is maybe a bug ? do you have more details ? (maybe we should continue that point in a Leshan issue ?)

eclipse-leshan/leshan#1622

@mkgillmore
Copy link

Per OMA DMSO discussion, should this return 2.04 instead and we clarify how to handle 2.05 response with no content

@sbernard31
Copy link

@mkgillmore,

should this return 2.04 instead

is this a question ? OR do you mean that a READ Response should be a 2.04 ?

AFAIK, this doesn't follow CoAP RFC... a READ request (so a CoAP GET) should only accept 2.05 Content as successful response.

Eventually, 2.03 Valid but this is only when ETAG is used and value doesn't change since last GET, so this is out of topic here.

@sbernard31
Copy link

Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object
Instance.

I rethink about that and if we strictly follow SenML spec, I don't think the "may be empty" could be about SenML.
(It could concern others content format but not SenML)

Why ? because it seems in SenML "[ ]" is valid but "" (so empty payload) is not.

See rfc8428§section-11 :

SenML-Pack = [1* record]

 record = {
   ? bn => tstr,        ; Base Name
   ? bt => numeric,     ; Base Time
   ? bu => tstr,        ; Base Units
   ? bv => numeric,     ; Base Value
   ? bs => numeric,     ; Base Sum
   ? bver => uint,      ; Base Version
   ? n => tstr,        ; Name
   ? u => tstr,        ; Units
   ? s => numeric,     ; Sum
   ? t => numeric,     ; Time
   ? ut => numeric,    ; Update Time
   ? ( v => numeric // ; Numeric Value
       vs => tstr //   ; String Value
       vb => bool //   ; Boolean Value
       vd => binary-value ) ; Data Value
   * key-value-pair
}

So : Empty Object Instance === [SenML encoding] ===> Empty SenML-Pack ===[JSON encoding]==> [ ]

@dnav
Copy link
Member Author

dnav commented Jun 17, 2024

Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object
Instance.

I rethink about that and if we strictly follow SenML spec, I don't think the "may be empty" could be about SenML. (It could concern others content format but not SenML)

Reading the TS, I understand "empty payload" as the absence of a payload in the CoAP packet, not an empty string.

Eg: Type=ACK, Code=2.05, MID=0x7d35, Token=0x20

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | 1 | 2 |   1   |    2.05=69    |          MID=0x7d35           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     0x20      |
   +-+-+-+-+-+-+-+-+

Hence my point that an "empty payload" should not have a Content-format, since the content-format option "indicates the representation format of the message payload." (RFC 7252)

It is not not the same thing as an "Empty SenML payload" which is indeed an empty array as you wrote.

Eg: Type=ACK, Code=2.05, MID=0x7d35, Token=0x20, option Content-format=110, Payload= "[]"

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | 1 | 2 |   1   |    2.05=69    |          MID=0x7d35           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     0x20      |   12   |   1  |  SenML JSON   |1 1 1 1 1 1 1 1|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      '['      |      ']'      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

@mkgillmore
Copy link

mkgillmore commented Jun 17, 2024 via email

@sbernard31
Copy link

Shouldn’t the response be 2.04 for no content? https://datatracker.ietf.org/doc/html/rfc7252#section-5.9.1.4

If you read the section you shared :
"This Response Code is like HTTP 204 "No Content" but only used in response to POST and PUT requests."

And reading https://datatracker.ietf.org/doc/html/rfc7252#section-5.8.1 :
"Upon success, a 2.05 (Content) or 2.03 (Valid) Response Code SHOULD be present in the response."

So for me this is pretty clear : only 2.05 (Content) can be used for GET.
(2.03 Valid can also be used but for GET but only when ETag is used)

IMHO, using 2.04 in this case would be a mistake.

@sbernard31
Copy link

I also find https://datatracker.ietf.org/doc/html/rfc7252#section-5.5.1 :

Implementation Note: On a quality-of-implementation level, there is
a strong expectation that a Content-Format indication will be
provided with resource representations whenever possible. This is
not a "SHOULD" level requirement solely because it is not a
protocol requirement, and it also would be difficult to outline
exactly in what cases this expectation can be violated.

Replying to #579 (comment)

I understand your point.

So the question is :

Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object
Instance. In this case the response code is still 2.05 Content.

Should that sentence ☝️ be interpreted as :

  1. An "empty payload" without Content Format is acceptable to express empty LWM2M Node (Object, Object Instance, Multi-Instance Resource )
  2. OR Some Content Format encoding empty LWM2M Node could lead to empty payload.

It seems we didn't find any argument allowing to reject one of them.
But there some pro/con for each solutions.

1. No content format allowed :
Pro :

  • in rare case you read empty LWM2M Node, you save few byte (2 bytes ?)

Con :

  • implementers need to handle a special case at serialization (optionally) and de-serialization (mandatory)

Note : if Accept option is used in GET request, it seems that Content Format is mandatory, see : https://datatracker.ietf.org/doc/html/rfc7252#section-5.10.4
Note : Does this special case will be only about GET ? or will it be about POST/PUT too ?

2. content format mandatory
Pretty much the opposite than above without any problem with Accept option or question about POST/PUT.

My personal opinion, I prefer 2.) It seems to me it's more in line with CoAP RFC spirit.

@sbernard31
Copy link

sbernard31 commented Jun 18, 2024

@mlasch, @LukasWoodtli from Wakaama project.

Do you have any opinion about that ?
How wakaama behaves without Content Format ?

@dnav
Copy link
Member Author

dnav commented Jun 20, 2024

Just on this point:

implementers need to handle a special case at serialization (optionally) and de-serialization (mandatory)

Your implementation already handles the special case of having a Content-format option but no payload.

A naive design would invoke the parser matching the content-format value. And for most of the formats, the parser would return an error as a 0-length buffer is not valid.

@sbernard31
Copy link

Your implementation already handles the special case of having a Content-format option but no payload.

I didn't talk about Leshan in particularly. (maybe current Leshan behavior is a mistake)
I was talking in a general way and I agree this is not a big con.
As I said there is no big PRO or CON else one obvious solution could be easily chosen.

A naive design would invoke the parser matching the content-format value. And for most of the formats, the parser would return an error as a 0-length buffer is not valid.

Yep from my point of view this matches with interpretation :
"Some Content Format (not all) encoding empty LWM2M Node could lead to empty payload."

@dnav
Copy link
Member Author

dnav commented Jun 21, 2024

Just to summarize my inputs:

Following #213, LwM2M allows CoAP 2.05 response messages to have no CoAP payload as stated in the CoAP Transport Binding section:

An Object Instance, a Resource or a Resource Instance are read by sending a CoAP GET to the corresponding path. The
response includes the value in the corresponding format according to the specified Content-Format (see [LwM2M
CORE]). The request MAY specify an Accept option containing the preferred Content-Format to receive. When the
specified Content-Format is not supported by the LwM2M Client, the request MUST be rejected (error code 4.06 as
defined in [CoAP]).
Note that the response payload may be empty, for instance when performing a Read operation on an Object with no
Object Instance. In this case the response code is still 2.05 Content.

In such a case, should the CoAP response include a Content-Format option or not?

If yes, what should be the indicated content-format?

For most of the formats used in LwM2M, an empty input buffer is not valid:

Content-format option
SenML CBOR Not a valid SenML.
SenML JSON Not a valid JSON.
TLV Valid?
LwM2M CBOR Not a valid LwM2M CBOR.
Text Valid.
Opaque Valid.

@sbernard31
Copy link

In such a case, should the CoAP response include a Content-Format option or not?

I guess this will depend what meaning OMA member will choose for "Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object Instance. In this case the response code is still 2.05 Content."
Either It means :

  1. An "empty payload" without Content Format is acceptable to express empty LWM2M Node (Object, Object Instance, Multi-Instance Resource )
  2. OR Some Content Format encoding empty LWM2M Node could lead to empty payload.

As I prefer 2, I would answer Yes it should.

If yes, what should be the indicated content-format?

IMHO, the question doesn't really arise.
Client choose to encode a LWM2M node in a given Content Format (maybe its preferred one OR the one requested by Accept option), then in some case it could result in an empty payload.

For most of the formats used in LwM2M, an empty input buffer is not valid:

I'm not sure but an empty string in Text format is valid ? and empty string is encoded as empty payload or I missed something ?
Except that point, I pretty agree with that table.

Maybe this sentence 👇 should just be deleted ? 🤷‍♂️
"Note that the response payload may be empty, for instance when performing a Read operation on an Object with no Object Instance. In this case the response code is still 2.05 Content."

@dnav
Copy link
Member Author

dnav commented Jun 24, 2024

I'm not sure but an empty string in Text format is valid ? and empty string is encoded as empty payload or I missed something ?
Except that point, I pretty agree with that table.

My point was that an empty string is the one-byte buffer 0x00.

@sbernard31
Copy link

My point was that an empty string is the one-byte buffer 0x00.

At CoAP level, I don't think it is encoded like this. 🤔
At least, I didn't find anything about that in RFCs (but maybe I missed something)
I tested with java-coap and californium, looking with wireshark => there is no payload at all.
So, let me know if I'm wrong and so if issue should be opened to that project.

@dnav
Copy link
Member Author

dnav commented Jun 25, 2024

Double checking LwM2M dat types and RFC 3629, indeed you are right. I edited the table.

@mkgillmore
Copy link

@dnav is there a pull request for this table edit?

@LukasWoodtli
Copy link

@mlasch, @LukasWoodtli from Wakaama project.

Do you have any opinion about that ? How wakaama behaves without Content Format ?

Sorry for the late answer. I‘m no so involved into the client implementation of Wakaama.
It looks like there is not a generic way in reading objects from a client in Wakaama. There are some examples that show how it can be done. But they are not part of the library itself.
As far as I can tell the Wakaama client would send response with a content type. But I’m not sure how it would encode an empty payload.

In general I think it would be nice if we could send a CoAP packet with no content type and an empty payload in such a case. But not sure if that would comply with the specs of CoAP and LaM2M.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants