Closed trampster closed 4 years ago
Changing
if (exchange.Request.IsCancelled) {
to
if (exchange.Request.IsCancelled || exchange.Request.Observe == 1)
Fixes the issue for us
File and line number would be useful
Ah yes sorry,
https://github.com/Com-AugustCellars/CoAP-CSharp/blob/master/CoAP.NET/Stack/ObserveLayer.cs
line 127
I can submit a pull request if that helps.
Are you not hitting line 112 in Server/ServerMessageDeliverer.cs?
By itself that does not look like it would prevent a new refresh from occurring all it does is to tell the server that the observe that it has returned as being marked canceled is to be canceled.
I am wondering why line 86 in CoapObserveRelation.cs which sets the IsCancelled to true is not lasting into this return point.
There are two Requests in CoapObserveRelation.cs ProactiveCancel(),
Line 73 makes a new request to send the cancel, this one is not marked as cancelled. Line 86 is the original observe request this is the one that is marked as cancelled.
It's the new request (line 73) that causes the problem because it is an observe and is not cancelled so it gets refreshed. My change above checks that this new 'Request to cancel' doesn't get refreshed.
The real error is that for an Observe=1 request "The resulting response MUST NOT include an Observe Option". I think it makes sense to also mark the second request with ObserveReconnect = false so that the second condition will fail and it 1) will give the client a response to the proactive cancel and 2) not setup the reconnect.
The Resulting response does not include an Observe Option
If you don't have have an observe option in the response, how is line 126 true?
So the plot thickens, The response MID doesn't match the request. The response is from the observe (before it was cancelled) but the request in the exchange (exchange.Request) is the cancel request. They have the same Token but different MID so should not have been put together.
When the actual Cancel response arrives it doesn't have the observe option set.
So looks like there is a bigger bug here.
I had started to wonder if it was a race condition here. The problem is that every MID for a notification is going to be different from the original request. But the response to the cancel request should have a MID to match with. The same token is going to be used for all of them. I will need to ponder.
Thanks, can I just say that it is amazing to work with an open source project where the maintainer is so responsive.
I think that pull request #85 should fix your problem. I am going to sit on it for a few days before merging it so that I have a chance to recover from it and see if it needs some fixes.
Part of drop 1.10.0
CoapObserveRelation.ProactiveCancel() creates a new request to send the observe cancel. Then in the ObserveLayer in ReceiveResponse that request to cancel is not itself cancelled (IsCancelled is false) so PrepareReregistration is called which refreshes the observe that was just cancelled.
This results in the cancelled observe coming back.