Subject: RE: [Sip] Issue: Expiration of temp-gruu

From: <[email-masked]>
Date: Thu, 1 Mar 2007 08:01:36 +0200

Hi,

>The client would just generate a register refresh, changing the callid.
>When it does this, it will, by the algorithm above, invalidate its 
>temp-gruu locally. If we specify that the server does the same, then 
>this provides a way for a client forcefully invalidate all previous 
>temp-gruu without loss of connectivity.

The proposed algorithm would unfortunately have a conflict
to what RFC 3261 currently specifies for Call-ID handling for
REGISTER refreshes in section 10.2:

      Call-ID: All registrations from a UAC SHOULD use the same Call-ID
           header field value for registrations sent to a particular
           registrar.

           If the same client were to use different Call-ID values, a
           registrar could not detect whether a delayed REGISTER request
           might have arrived out of order. 

Seems that this rule has been specified to avoid another race
condition e.g. by the UAC at first refreshing the registration
and right thereafter removing the binding. If these two messages
would arrive over UDP to the registrar in the opposite order the
UAC would believe to have successfully deregistered while the
registrar would believe the UAC to have registered again.

Thus solving the race condition like that for GRUU, another
race condition would be opened for handling registrations in
general.

Regards,

Erkki

>-----Original Message-----
>From: ext Jonathan Rosenberg [mailto:[email-masked]] 
>Sent: 28.February.2007 18:32
>To: Jonathan Rosenberg
>Cc: SIP IETF; Paul Kyzivat
>Subject: Re: [Sip] Issue: Expiration of temp-gruu
>
>So, its now a month and a half since posting this, and days before the 
>deadline I am getting to do this. And of course, as always seems to 
>happen, on re-reading the threads and documents to re-cache 
>the issues, 
>I find another problem :(
>
>The algorithm below works fine, but omits a case. The case that is 
>omitted is where the server doesn't send a partial notification, and 
>instead sends a full-state notification that comes after the 
>registration is refreshed. The flow is like this:
>
>
>UA        Reg
>
>                (reg decides to shorten duration to 5s)
>
>NOTIFY (5s)
><-----------
>
>REGISTER       (misses the window, and registration lapses briefly)
>------------>
>200 OK
><------------
>
>NOTIFY (1hr)   (reg never bothered to send NOTIFY for expiration since
><------------   it was refreshed a second later. So, rather 
>than sending
>                 two notifications, it combined and sent one with the
>                 most recent state)
>
>
>In this case, the 'glitch' that occurred - the temporary expiration of 
>the contact followed by its re-registration, is NEVER known by the 
>client. So, the server invalidated all of the temp-gruu, but 
>the client 
>doesn't know it.
>
>One solution is to REQUIRE a server to always send all state changes, 
>never to combine them. I don't like this, since you still might have 
>cases where the client misses a notification due to packet loss or 
>something, and then you have the same problem over again. 
>IMHO, you need 
>a way for the client to be sure that it is in sync with the server on 
>which temp-gruu are valid, and which are not.
>
>Fortunately, the solution here is relatively straightforward. The 
>reg-event notifications include the cseq value present in the 
>registration that first registered this contact. RFC 3680 already 
>includes the total time elapsed since this contact was registered, but 
>since we're dealing with race conditions, the timestamps aren't good 
>enough. This would be a new element, <orig-cseq>, a child to <contact> 
>in the reg-event XML.
>
>Whenever the client gets a reg-event notification, it invalidates any 
>temp-gruu learned in a REGISTER that had a cseq value earlier than the 
><orig-cseq>.
>
>This provides a way for the client to, at any time, 
>synchronize its set 
>of valid temp-gruu with what the server has. So, it resolves this 
>additional case above, in addition to providing a way to verify 
>synchornization at any time, in case the client gets confused.
>
>Now, an important point here. Its not just the cseq, its also callid. 
>The callid is part of this since cseq are scoped within a particular 
>callid (as defined in RFC 3261). Interestingly, this provides, as a 
>side-effect, a way for a client to tell the server to 
>invalidate temp-gruu.
>
>The client would just generate a register refresh, changing the callid.
>When it does this, it will, by the algorithm above, invalidate its 
>temp-gruu locally. If we specify that the server does the same, then 
>this provides a way for a client forcefully invalidate all previous 
>temp-gruu without loss of connectivity.
>
>This is trivially done statelessly, by changing the hash algorithm to 
>use the orig-cseq and call-id in the hash, rather than wallclock time.
>
>The main drawback really is that its a bit of feature creep. Again.
>
>My recommendation is to do it anyway, since I need to put about 95% of 
>it in there just to deal with the race condition problem described 
>above. The extra 5% is just an instruction to servers to invalidate 
>temp-gruu when the call-id changes. That bit is what provides the 
>feature whereby the client can forcefully expire temp-gruu.
>
>Thoughts?
>
>-Jonathan R.
>
>Jonathan Rosenberg wrote:
>
>> This thread is a month old, but I want to revise GRUU and 
>get this done. 
>> This is really the only issue that is outstanding, I think.
>> 
>> To refresh everyones memory, the issue being dsicussed is this. 
>> Temp-GRUU expire when the last contact with the instance ID 
>expires. In 
>> normal cases, the expiration is known to the UA. However, there are 
>> cases where there is a forceful de-registration, for 
>example. In these 
>> cases, the UA will not know about it, and it won't know whether its 
>> temp-gruu remain valid.
>> 
>> We've seen three proposals for how to deal with this:
>> 
>> 1. include a parameter in the Contact header field of the REGISTER 
>> response, indicating the time at which the first contact with that 
>> instance ID was registered. When this changes in a REGSITER 
>response, 
>> the UA knows its older temp-gruu are invalid.
>> 
>> 2. the UA uses a reg-event subscription, and it gets a 
>NOTIFY when the 
>> contacts are de-registered. As long as the UA gets the notification 
>> indicating that the de-registration has happened, this works 
>reasonably 
>> well.
>> 
>> 3. the UA can use an OPTIONS sent to a temp-gruu to verify 
>that it still 
>> works
>> 
>> (2) and (3) require no new mechanism, just explanation. (1) would 
>> require new mechanism.
>> 
>> Now, I was in the process of working through some details on 
>this, and 
>> ran into problems. In particular, we ultimately need to be able to 
>> specify an algorithm that clearly tells a UA which of its 
>temp GRUU are 
>> valid, and which are expired. If we are using the reg-event 
>subscription 
>> to figure this out, the obvious algorithm would be to expire all 
>> temp-gruu learned in REGISTER responses prior to this notification. 
>> However, that is imprecise. What about a REGISTER that happens very 
>> close in time to the NOTIFY? Indeed, this is very likely to 
>be the case 
>> when the reg-event is shortening the expiration in order to 
>ask the user 
>> to explicitly re-REGISTER, but the time was a bit too short and the 
>> re-REGISTER is close to the boundary. If a NOTIFY comes 
>indicating that 
>> the contact did expire, how do you *know* if that REGISTER came in 
>> before or after? You could wait for the next NOTIFY, and try and 
>> correlate it with the REGISTER you just completed.
>> 
>> One way to do that is with CSeq. The reg-event package includes the 
>> option of having CSeq numbers. If we assume these are always 
>used (they 
>> are optional), the algorithm is a bit easier. Each temp-gruu is 
>> associated with the CSeq of the REGISTER in which it was 
>learned. When a 
>> NOTIFY comes indicating that the registration has expired, 
>you look to 
>> see if its a partial or full state NOTIFY. In the case of 
>partial, if 
>> the NOTIFY explicitly removes a contact, you invalidate all 
>temp-gruu 
>> learned in register responses prior to or equal to the CSeq in the 
>> contact. If the case of a full state NOTIFY, if the contact 
>is absent, 
>> the UA marks all temp-gruu as suspect. On the first NOTIFY that 
>> indicates the Contact is re-registered (I assume the UA is 
>> re-registering), the UA invalidates all temp-gruu learned by 
>REGISTER 
>> responses whose CSeq is less than the one in the NOTIFY. All 
>others are 
>> considered valid.
>> 
>> This algorithm is assuming some very specific behavior from 
>registrars 
>> that are doing reg-event with GRUU. Namely, they always send 
>CSeq, even 
>> when indicating expiration of a contact. We'd need to specify this, 
>> probably as a note in gruu-reg-event.
>> 
>> Comments on this algorithm? If this is OK I will update GRUU 
>based on 
>> this and we can ship it. Finally. Really this time.
>> 
>> -Jonathan R.
>> 
>> 
>> Scott Lawrence wrote:
>> 
>>> On Mon, 2006-12-04 at 17:15 -0500, Paul Kyzivat wrote:
>>>
>>>> Scott,
>>>>
>>>> Its certainly true that a gruu can always be tested to see if it 
>>>> works. That would however raise the question of when one 
>ought to do 
>>>> the test. In normal cases you will know the status of your gruu by 
>>>> regular methods, so you would have no reason to test it. 
>So you would 
>>>> have to test whenever you thought failure might have negative 
>>>> consequences. Some of the times when failure might have bad 
>>>> consequences are: when responding to an incoming INVITE, 
>and any time 
>>>> during a dialog. I guess you could send an OPTIONS and await the 
>>>> response before responding to an INVITE, and it might even 
>be masked 
>>>> by alerting, but it seems kind of annoying to have to do 
>that. But no 
>>>> matter how often you do it during a dialog you still might 
>miss the 
>>>> moment your gruu becomes invalid and the other end of the dialog 
>>>> sends you a message. (Extremely unlikely, but possible.)
>>>>
>>>> I think the other existing solutions get "pretty close", 
>and OPTIONS 
>>>> doesn't significantly improve on that.
>>>
>>>
>>>
>>> I don't like requiring the registrar to return a timestamp 
>because it's
>>> yet another piece of state that it has to keep for every 
>registration.
>>>
>>> I don't think it actually helps all that much - going back to your
>>> original problem statements:
>>>
>>>
>>>> 3) the UA may attempt to refresh the registration, but be too slow,
>>>>    so that the reregistration arrives after the prior one expires
>>>> 4) some other UA may deregister all the registrations, including
>>>>    the one by this UA. (When the UA decides it should refresh the
>>>>    registration it will actually create a new one.)
>>>> 5) the registrar may remove the registration administratively
>>>> 6) the registrar may crash and restart, losing all its 
>registrations
>>>
>>>
>>>
>>> Case 3 can be avoided by just not waiting too long (overlap by a few
>>> minutes instead of a few seconds - if that's still 
>problematic then you
>>> probably have other problems that are worse anyway).
>>>
>>> Cases 4,5, and 6 are essentially all the same from the 
>point of view of
>>> the UA; your registration state at the server is lost 
>because of some
>>> event you are not aware of.  This is true of any 
>registration, and is
>>> not specific to temp-gruu or public gruu; it can happen 
>with a Contact
>>> value you provide without gruu at all.  A gruu is slightly 
>worse in that
>>> loosing the state can affect in-dialog requests for 
>established dialogs,
>>> but I think that's just an unavoidable chance that you take when you
>>> choose to use a gruu of either kind.  Put another way, if you use a
>>> gruu, you accept the fact that you're relying on an 
>additional service
>>> for in-dialog connectivity - it's either worth the benefits 
>or it isn't.
>>>
>>>
>>>
>>>
>> 
>
>-- 
>Jonathan D. Rosenberg, Ph.D.                   600 Lanidex Plaza
>Cisco Fellow                                   Parsippany, NJ 
>07054-2711
>Cisco Systems
>[email-masked]                              FAX:   (973) 952-5050
>http://www.jdrosen.net                         PHONE: (973) 952-5000
>http://www.cisco.com
>
>_______________________________________________
>Sip mailing list  https://www1.ietf.org/mailman/listinfo/sip
>This list is for NEW development of the core SIP Protocol
>Use [email-masked] for questions on current sip
>Use [email-masked] for new developments on the application of sip
>

_______________________________________________
Sip mailing list  https://www1.ietf.org/mailman/listinfo/sip
This list is for NEW development of the core SIP Protocol
Use [email-masked] for questions on current sip
Use [email-masked] for new developments on the application of sip

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 01 Mar 2007 23:13:41 -0500

inline.

> registrar would believe the UAC to have registered again.

Sure; if the client wants to refresh and remove it would use the same 
call-id. There is no race here as long as the client doesn't create one. 
If the client wants to remove its temp-gruus it would change call-ID and 
then wait for a response before doing the next registration. With that 
there is never a race. Thats why this is a SHOULD and not a MUST.

-Jonathan R.

-- 
Jonathan D. Rosenberg, Ph.D.                   600 Lanidex Plaza
Cisco Fellow                                   Parsippany, NJ 07054-2711
Cisco Systems
[email-masked]                              FAX:   (973) 952-5050
http://www.jdrosen.net                         PHONE: (973) 952-5000
http://www.cisco.com