Subject: [sipcore] UPDATE, reINVITE rejections, and session-state rollback

From: Byron Campen <[email-masked]>
Date: Mon, 11 Oct 2010 12:43:07 -0500

Sending to the authors of the offeranswer and reinvite drafts, since I am not sure which bucket this would fall in:

	Consider the following. In all cases, this is within a reINVITE transaction, after an offer/answer exchange has completed using 100rel (which kind is not important), that is being rejected by the server side due to some unspecified error:

                 A          B
                 |<---------| INVITE/500
                 |          |
                 |          |
  UPDATE (offer) |--------->|
                 |          |
                 |<---------| UPDATE/200 (answer)

                 A          B
  UPDATE (offer) |---\  /---| INVITE/500
                 |    \/    |
                 |    /\    |
                 |<--/  \-->|
                 |          |
                 |<---------| UPDATE/200 (answer)

                 A          B
                 |        /-| INVITE/500
                 |       /  |
  UPDATE (offer) |------/-->|
                 |     /    |
                 |<---/-----| UPDATE/200 (answer)
                 |   /      |
                 |<-/       |

	All of these look identical to B; UPDATE offer/answer completes after the end of the INVITE transaction. However, A sees them very differently. B cannot know that something unusual has happened. Also consider the following cases:

                 A          B
  UPDATE (offer) |--------->|
                 |          |
                 |<---------| UPDATE/200 (answer)
                 |          |
                 |<---------| INVITE/500

                 A          B
  UPDATE (offer) |--------->|
                 |          |
                 |       /--| UPDATE/200 (answer)
                 |      /   |
                 |<----/----| INVITE/500
                 |    /     |
                 |<--/      |

	Again, these look the same to B, but different to A. What is the best approach to ensuring that session-state is consistent on both ends in all of these cases? It seems to me that one way would be to specify that rollback of a reINVITE does not invalidate session-state established with an UPDATE, regardless of whether that UPDATE transaction occurred (or appeared to have occurred) during the reINVITE transaction. If we insist that session-state established with an in-reINVITE UPDATE be rolled back (the current language says that both sides must roll back to the session-state in use prior to the reINVITE), then there is no way to ensure consistent rollback on both ends, even if everything has the same rollback logic, because what appears to be an in-reINVITE UPDATE on one end may appear to be after the reINVITE transaction on the other end. If any portion of the UPDATE transaction appeared to have happened within the reINVITE transaction, then the observing UA must send a subsequent UPDATE to re-sync (since there is no guarantee that the other end saw the UPDATE within the reINVITE transaction). This is likely to cause glare, unless we put asymmetric timers on the re-sync, and even then there will be a delay similar to that caused by glare.

	My gut says that it would be better to not rollback session-state established by an UPDATE, under any circumstances. But, there may be situations where the session-state established in an UPDATE is contingent on the reINVITE succeeding it. Would it be appropriate to say that if a UA "feels" this way, it is responsible for re-syncing? Or is there something I am missing here?

Best regards,
Byron Campen

---

From: [email-masked]
Date: Tue, 12 Oct 2010 17:24:25 +0800

Hi Byron Campen,

Before getting into the details, I'd like to check does the "INVITE/500" 
just means the 5xx of INVITE?

Thanks,

Gao

>    Sending to the authors of the offeranswer and reinvite drafts, 
> since I am not sure which bucket this would fall in:
> 
>    Consider the following. In all cases, this is within a reINVITE 
> transaction, after an offer/answer exchange has completed using 
> 100rel (which kind is not important), that is being rejected by the 
> server side due to some unspecified error:
> 
>                  A          B
>                  |<---------| INVITE/500
>                  |          |
>                  |          |
>    All of these look identical to B; UPDATE offer/answer completes 
> after the end of the INVITE transaction. However, A sees them very 
> differently. B cannot know that something unusual has happened. Also
> consider the following cases:
> 
>                  A          B
>    Again, these look the same to B, but different to A. What is the 
> best approach to ensuring that session-state is consistent on both 
> ends in all of these cases? It seems to me that one way would be to 
> specify that rollback of a reINVITE does not invalidate session-
> state established with an UPDATE, regardless of whether that UPDATE 
> transaction occurred (or appeared to have occurred) during the 
> reINVITE transaction. If we insist that session-state established 
> with an in-reINVITE UPDATE be rolled back (the current language says
> that both sides must roll back to the session-state in use prior to 
> the reINVITE), then there is no way to ensure consistent rollback on
> both ends, even if everything has the same rollback logic, because 
> what appears to be an in-reINVITE UPDATE on one end may appear to be
> after the reINVITE transaction on the other end. If any portion of 
> the UPDATE transaction appeared to have happened within the reINVITE
> transaction, then the observing UA must send a sub
>  sequent UPDATE to re-sync (since there is no guarantee that the 
> other end saw the UPDATE within the reINVITE transaction). This is 
> likely to cause glare, unless we put asymmetric timers on the re-
> sync, and even then there will be a delay similar to that caused by 
glare.
> 
>    My gut says that it would be better to not rollback session-state
> established by an UPDATE, under any circumstances. But, there may be
> situations where the session-state established in an UPDATE is 
> contingent on the reINVITE succeeding it. Would it be appropriate to
> say that if a UA "feels" this way, it is responsible for re-syncing?
> Or is there something I am missing here?
> 
> Best regards,
> Byron Campen
> 

--------------------------------------------------------
ZTE Information Security Notice: The information contained in this mail is solely property of the sender's organization. This mail communication is confidential. Recipients named above are obligated to maintain secrecy and are not permitted to disclose the contents of this communication to others.
This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the originator of the message. Any views expressed in this message are those of the individual sender.
This message has been scanned for viruses and Spam by ZTE Anti-Spam system.

---

From: Byron Campen <[email-masked]>
Date: Tue, 12 Oct 2010 09:19:18 -0500

Any non-dialog-killing failure response will do here. My suspicion is that a 500 will be the most commonly seen such response in the wild, but I could be mistaken.

Best regards,
Byron Campen

> 
> Hi Byron Campen, 
> 
> Before getting into the details, I'd like to check does the "INVITE/500" just means the 5xx of INVITE? 
> 
> Thanks, 
> 
> Gao 
> 
> > sync, and even then there will be a delay similar to that caused by glare.
> > 
> _______________________________________________
> sipcore mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/sipcore

---

From: Gonzalo Camarillo <[email-masked]>
Date: Thu, 14 Oct 2010 14:54:31 +0300

Hi Byron,

> Would it be appropriate to say that if a UA "feels" this way, it is responsible for re-syncing?

yes, that is what the re-INVITE draft says:

http://tools.ietf.org/html/draft-ietf-sipcore-reinvite-06#section-3.4

Figure 5 shows a message flow with a race condition similar to the ones
you are referring to:

http://tools.ietf.org/html/draft-ietf-sipcore-reinvite-06#page-16

Thanks,

Gonzalo

On 11/10/2010 8:43 PM, Byron Campen wrote:
> 	Again, these look the same to B, but different to A. What is the best approach to ensuring that session-state is consistent on both ends in all of these cases? It seems to me that one way would be to specify that rollback of a reINVITE does not invalidate session-state established with an UPDATE, regardless of whether that UPDATE transaction occurred (or appeared to have occurred) during the reINVITE transaction. If we insist that session-state established with an in-reINVITE UPDATE be rolled back (the current language says that both sides must roll back to the session-state in use prior to the reINVITE), then there is no way to ensure consistent rollback on both ends, even if everything has the same rollback logic, because what appears to be an in-reINVITE UPDATE on one end may appear to be after the reINVITE transaction on the other end. If any portion of the UPDATE transaction appeared to have happened within the reINVITE transaction, then the observing UA must send a 
subsequent UPDATE to re-sync (since there is no guarantee that the other end saw the UPDATE within the reINVITE transaction). This is likely to cause glare, unless we put asymmetric timers on the re-sync, and even then there will be a delay similar to that caused by glare.

---

From: Byron Campen <[email-masked]>
Date: Thu, 14 Oct 2010 08:46:01 -0500

Perhaps I phrased my question poorly. My question wasn't so much about what a UA should do when it thinks the session is out of sync, but whether it thinks the session is out of sync in the specific case I posed. But, I suppose that any time we get a reINVITE that is rejected after an offer/answer exchange has been completed, whether or not there had been an UPDATE thrown into the mix, we should assume the worst and re-sync. This will lead to glare fairly often, but we are already in a relatively rare corner-case, so I can see this being acceptable.

Best regards,
Byron Campen

---

From: Gonzalo Camarillo <[email-masked]>
Date: Thu, 14 Oct 2010 16:54:34 +0300

Hi,

the condition for resynching given in the draft is when the UA "receives
an error response to a re-INVITE that undoes already-executed changes
within the re-INVITE". The draft talks about several situation where UAs
can go out of synch.

In any case, as you suggest in your email, we are talking about corner
cases.

Cheers,

Gonzalo

---

From: Byron Campen <[email-masked]>
Date: Thu, 14 Oct 2010 09:06:50 -0500

Alright, that's pretty clear. Now, there is still the question of what happens when the UAS is aware of the specification, but is forced to send a 500 or similar anyway, and then the 500 crosses the UPDATE on the wire, like so:

                    |        /-| INVITE/500
                    |       /  |
                    |<-----/---| UPDATE (re-sync offer)
                    |     /    |
UPDATE/200 (answer) |----/---->| 
                    |   /      |
                    |<-/       |

	We cannot use the ACK for the 500, since it is hop-by-hop, and if the UAC doesn't re-sync, UAS's attempt to re-sync fails. Are we content with saying that the UAS cannot recover from this? We _could_ avoid this problem by having a rule that says "If you're the UAS, and you rejected the reINVITE with already executed offer/answer changes, you MUST send your re-sync offer in an INVITE", since the other end will reject our re-sync if it beats the 500.

Best regards,
Byron Campen

---

From: Gonzalo Camarillo <[email-masked]>
Date: Thu, 14 Oct 2010 18:17:09 +0300

Hi Byron,

if the UAS is compliant with the new spec, it would not send the 500. It
would send the UPDATE to get everything in synch and then send a 200 OK
to the INVITE. If the UAS does not support the new spec but the UAC
does, the UAC will notice the possible race condition and send an UPDATE
to resynch. If none of them supports the new spec... well, there is
nothing we can do in that case :o)

Cheers,

Gonzalo

On 14/10/2010 5:06 PM, Byron Campen wrote:
>>>>> 	Again, these look the same to B, but different to A. What is the best approach to ensuring that session-state is consistent on both ends in all of these cases? It seems to me that one way would be to specify that rollback of a reINVITE does not invalidate session-state established with an UPDATE, regardless of whether that UPDATE transaction occurred (or appeared to have occurred) during the reINVITE transaction. If we insist that session-state established with an in-reINVITE UPDATE be rolled back (the current language says that both sides must roll back to the session-state in use prior to the reINVITE), then there is no way to ensure consistent rollback on both ends, even if everything has the same rollback logic, because what appears to be an in-reINVITE UPDATE on one end may appear to be after the reINVITE transaction on the other end. If any portion of the UPDATE transaction appeared to have happened within the reINVITE transaction, then the observing UA must sen
d 
>> a

---

From: Byron Campen <[email-masked]>
Date: Thu, 14 Oct 2010 14:26:58 -0500

If it is possible to, then sure. But is it really appropriate to just swallow all non-offer/answer-related errors in this case? Say an exception gets thrown, or some extension decides that it needs to reject the INVITE transaction for a very specific reason that the other end absolutely needs to know about? I definitely agree that sending something like a 488 (or other session-related errors) is something that is both completely unnecessary and harmful, but I am less sure about other error conditions.

Best regards,
Byron Campen

---

From: Gonzalo Camarillo <[email-masked]>
Date: Fri, 15 Oct 2010 10:30:25 +0300

Hi Byron,

you could use a Reason header field in the UPDATE request in order to
communicate the error code to the UAC... but if you insist in sending
the error response anyway, then the UAS needs to decide between sending
the UPDATE immediately (the fastest way to resynch if it works, but it
may collide with an UPDATE from the UAC if the UAC decided to resynch as
well when it saw the error response) or implement a timer to wait for a
'short' time in case an UPDATE from the UAC arrives.

Cheers,

Gonzalo