Subject: [core] Message correlation with observe

From: Jim Schaad <[email-masked]>
Date: Mon, 17 Aug 2020 08:39:36 -0700

Klaus, Carsten,

I am trying to figure out if there is a problem in my head, and thus in my
code, or if it is in the design of the specs.

Start by setting up an observe operation:

C1:  GET /temperature  MID:10  Token: 0x4a Observe: 0
S1:  ACK 2.05 Content  MID:10 Token:0x4a Observe:12 Payload:22.9
S2: NON 2.05 Content MID:11 Token:0x4a Observe:44  Payload: 22.8

I now do a proactive cancel

C2: GET /temperature MID:15 Token:0x4a Observe:1

I now get two responses back

S3: NON 2.05 Content MID:99 Token:0x4a Observe:46 Payload: 22.2
S4: ACK 2.05 Content MID:15 Token:0x4a Payload: 22.1

As a human being, I automatically associate response S3 with request C1 and
response S4 with request C2.  However, my code base is associating response
S3 with request C2 and then drops response S4 on the floor because it is an
ACK to a message that has already received a response.  My code however is
doing something strange with the response S3 internally to deal with the
possibility of needing to refresh the observe relationship automatically
under the covers.

Other than playing with the use of the observe option in the response to
change the correlation algorithm, I believe that my code is correctly
following the spec and I just need to fix things about the refreshing in my
code.  The one odd side effect is that the client is not going to get a
response from the server that does not have an observe option in it, even if
the proactive cancel operation is a CON.  This seems to have cognitive
dissidence.   The observe relation is canceled, but there is no positive
notification of the fact.

I don't' believe that the use of OSCORE changes any thing in the above.  The
same thing is true for using a reliable transport since the MID is not
really used for correlation here, the token value is used here.

Is what my code does what the authors expected to occur?

Jim

---

From: Achim Kraus <[email-masked]>
Date: Mon, 17 Aug 2020 18:44:14 +0200

Hi Jim,

yes, that's one of the pain-points of reusing the token.
I'm not sure, if the rfc covers the processing of that scenario.
So I would also welcome an answer from Klaus and Carsten.

FMPOV, if someone, wants to cancel the observation,
I wait for a response without the observe option.
Sure, other implementations may also result in "acceptable behavior".

----- Californium, UdpMatcher, receiveResponse ---------------------
if (type != Type.ACK && !exchange.isNotification() &&
response.isNotification() && currentRequest.isObserveCancel()) {
    // overlapping notification and observation cancel request
    LOGGER.debug("ignoring notify for pending cancel {}!", response);
    cancel(response, receiver);
    return;
}
--------------------------------------------------------------------

best regards
Achim Kraus

Am 17.08.20 um 17:39 schrieb Jim Schaad:
> _______________________________________________
> core mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/core
>

---

From: Carsten Bormann <[email-masked]>
Date: Mon, 17 Aug 2020 18:54:18 +0200

Hi Jim, Achim,

> On 2020-08-17, at 18:44, Achim Kraus <[email-masked]> wrote:
> 

I cannot remember discussing the race condition Jim has identified, when we were discussing the fixes needed to be able to actively cease observing.
(I seem to remember most of this was done early 2014 in the CoAP-04 interop in London, after IETF89.)

Grüße, Carsten

---

From: <[email-masked]>
Date: Mon, 17 Aug 2020 18:27:39 +0100

Hi Jim,

With

> ....

As per https://tools.ietf.org/html/rfc7641#section-4.1

   If the Observe Option in a GET request is set to 1 (deregister), then
   the server MUST remove any existing entry with a matching endpoint/
   token pair from the list of observers and process the GET request as
   usual.  The resulting response MUST NOT include an Observe Option.

S3: therefore cannot be a match to C2: as it includes an Observe Option, so that at that point the server has not acknowledged the deregister.

As a deregister is in progress, S3: should not trigger an observer refresh in any underlying logic and should be dropped/ignored (as per Achim's solution).  Alternatively, (but not for TCP) a RST can be sent by the client on seeing S3: which may cause other confusion.

Regards

Jon

> -----Original Message-----
> From: core [mailto: [email-masked]] On Behalf Of Carsten Bormann
> Sent: 17 August 2020 17:54
> To: Achim Kraus
> Cc: Klaus Hartke; Core WG mailing list
> Subject: Re: [core] Message correlation with observe
> 
> Hi Jim, Achim,
> 
> I cannot remember discussing the race condition Jim has identified, when we
> were discussing the fixes needed to be able to actively cease observing.

---

From: Jim Schaad <[email-masked]>
Date: Mon, 17 Aug 2020 11:07:58 -0700

-----Original Message-----
From: [email-masked] <[email-masked]> 
Sent: Monday, August 17, 2020 10:28 AM
To: 'Carsten Bormann' <[email-masked]>; 'Achim Kraus' <[email-masked]>; 'Jim Schaad' <[email-masked]>
Cc: 'Klaus Hartke' <[email-masked]>; 'Core WG mailing list' <[email-masked]>
Subject: RE: [core] Message correlation with observe

Hi Jim,

With

> C2: GET /temperature MID:15 Token:0x4a Observe:1 ....

[JLS] That would be a change in the matching rules.  You might reject S3 at a higher level, but you have still matched it based on the token.  This would be a change in the match rules.

[JLS] I don't understand why the RST would not be sent in the TCP case.  This is the defined way to do a passive observe cancelation.  I don't remember seeing anything in the TCP document that would change this.   You might still not want to send the RST, but given that you then need to make sure that the active cancelation succeeds doing the RST might still be the best idea.

Jim

Regards

Jon

> I cannot remember discussing the race condition Jim has identified, 
> when we were discussing the fixes needed to be able to actively cease observing.

---

From: Carsten Bormann <[email-masked]>
Date: Mon, 17 Aug 2020 20:15:25 +0200

On 2020-08-17, at 20:07, Jim Schaad <[email-masked]> wrote:
> 
> [JLS] I don't understand why the RST would not be sent in the TCP case. 

That I can answer: You can’t.  RFC 8323 does not have message types.

Grüße, Carsten

---

From: Jim Schaad <[email-masked]>
Date: Mon, 17 Aug 2020 11:26:44 -0700

-----Original Message-----
From: Carsten Bormann <[email-masked]> 
Sent: Monday, August 17, 2020 11:15 AM
To: Jim Schaad <[email-masked]>
Cc: [email-masked]; Achim Kraus <[email-masked]>; Klaus Hartke <[email-masked]>; Core WG mailing list <[email-masked]>
Subject: Re: [core] Message correlation with observe

That I can answer: You can’t.  RFC 8323 does not have message types.
[JLS] So can I do a passive cancel of an observe?

Grüße, Carsten

---

From: <[email-masked]>
Date: Mon, 17 Aug 2020 20:01:46 +0100

Hi Jim,

See inline Jon>

Regards

Jon

> From: Jim Schaad [mailto: [email-masked]]
> Sent: 17 August 2020 19:27
> To: 'Carsten Bormann'
> Cc: [email-masked]; 'Achim Kraus'; 'Klaus Hartke'; 'Core WG mailing list'
> Cc: [email-masked]; Achim Kraus <[email-masked]>; Klaus
> Hartke <[email-masked]>; Core WG mailing list <[email-masked]>

Jon> No.  https://tools.ietf.org/html/rfc8323#section-7.4

   For CoAP over reliable transports, a client MUST explicitly
   deregister by issuing a GET request that has the Token field set to
   the Token of the observation to be canceled and includes an Observe
   Option with the value set to 1 (deregister).

~Jon

---

From: Jim Schaad <[email-masked]>
Date: Mon, 17 Aug 2020 12:25:55 -0700

-----Original Message-----
From: [email-masked] <[email-masked]> 
Sent: Monday, August 17, 2020 12:02 PM
To: 'Jim Schaad' <[email-masked]>
Cc: 'Achim Kraus' <[email-masked]>; 'Carsten Bormann' <[email-masked]>; 'Klaus Hartke' <[email-masked]>; 'Core WG mailing list' <[email-masked]>
Subject: RE: [core] Message correlation with observe

Hi Jim,

See inline Jon>

Regards

Jon

[JLS]  Sigh - yet another bug that needs to get fixed.

~Jon

---

From: Christian Amsüss <[email-masked]>
Date: Tue, 18 Aug 2020 08:51:06 +0200

Hello Jim, CoRE,

> S4: ACK 2.05 Content MID:15 Token:0x4a Payload: 22.1

In follow-up requests on the same token as Observe introduces them (and
I hope to generalize), an important theme is that responses that relate
to a particular follow-up message must be distinguishable as such where
it matters.

If just a plain refresh is sent, it doesn't matter whether a response
relates to the old or new request (especially, it's not necessarily
newer than the second request).

If the ETag set is changed (which is the only permissible alteration in
7641), it doesn't matter either (even though a new ETag clearly
indicates its generation after the second request).

If an OSCORE inner refresh happens, there is clear indication that it's
a later one because it only decrypts with the newest request's Partial
IV.

And if the observation is cancelled, a response only fits that by not
carrying the Observe option, as Jon pointed out.

Programmatically (at least in my implementation), all those responses
wind up in the same channel (which I call PlumbingRequest, but maybe
token channel or token subsocket would be more suitable), and it's up to
the requesting mechanism (observation) to sort them. If S4 happened to
overtake S3 on the wire, S4 would already be recognized as a response to
C2, "slamming the door" for everything that's not a response to C2 (just
like a higher observe value would make it disregard lower value
responses). By that time, any CON/ACK has already been handled as that's
purely on the Message-ID layer.

Kind regards
Christian

-- 
I shouldn't have written all those tank programs.
  -- Kevin Flynn

---

From: Michael Richardson <[email-masked]>
Date: Tue, 18 Aug 2020 16:16:39 -0400

having read the rest of the thread...

    > S4: ACK 2.05 Content MID:15 Token:0x4a Payload: 22.1

It seems to me that the new C2 operation, not being part of the original
Observe, ought to expect and match the MID:15.
C2 is new transaction, even if it really cancelling C1.
I understand that the MID would otherwise be ignored.

I can also see a client, upon seing S3, might assume C2 got lost, and
retransmit C2.

--
Michael Richardson <[email-masked]>, Sandelman Software Works
 -= IPv6 IoT consulting =-

---

From: Jim Schaad <[email-masked]>
Date: Tue, 18 Aug 2020 20:35:51 -0700

-----Original Message-----
From: Christian Amsüss <[email-masked]> 
Sent: Monday, August 17, 2020 11:51 PM
To: Jim Schaad <[email-masked]>
Cc: 'Klaus Hartke' <[email-masked]>; 'Carsten Bormann'
<[email-masked]>; 'Core WG mailing list' <[email-masked]>
Subject: Re: [core] Message correlation with observe

Hello Jim, CoRE,

> S4: ACK 2.05 Content MID:15 Token:0x4a Payload: 22.1

In follow-up requests on the same token as Observe introduces them (and I
hope to generalize), an important theme is that responses that relate to a
particular follow-up message must be distinguishable as such where it
matters.

If just a plain refresh is sent, it doesn't matter whether a response
relates to the old or new request (especially, it's not necessarily newer
than the second request).

If the ETag set is changed (which is the only permissible alteration in
7641), it doesn't matter either (even though a new ETag clearly indicates
its generation after the second request).

If an OSCORE inner refresh happens, there is clear indication that it's a
later one because it only decrypts with the newest request's Partial IV.

Programmatically (at least in my implementation), all those responses wind
up in the same channel (which I call PlumbingRequest, but maybe token
channel or token subsocket would be more suitable), and it's up to the
requesting mechanism (observation) to sort them. If S4 happened to overtake
S3 on the wire, S4 would already be recognized as a response to C2,
"slamming the door" for everything that's not a response to C2 (just like a
higher observe value would make it disregard lower value responses). By that
time, any CON/ACK has already been handled as that's purely on the
Message-ID layer.

[JLS] I guess I have some re-writing to do around this.  Is there anything
other than an Observe that is going to get this behavior?  I currently can't
think of anything at this time, but perhaps some blockwise stuff might end
up here.  My implementation currently creates a new silo for every request
and just shifts to the new silo for token matches, but that means that
history at the top of the silo has been lost such as in this case.  The
approach works fine for the request-ack-response world, but they did not
think hard enough about observe when then grafted it in.

Jim

Kind regards
Christian