Subject: Comments on "Supported:" header draft

From: "Adam B. Roach" <[email-masked]>
Date: Tue, 25 Jan 2000 18:46:45 -0600 (CST)

Re: http://www.ietf.org/internet-drafts/draft-ietf-sip-serverfeatures-00.txt

I've given the "Supported:" header draft a once-over, and have the
following feedback to offer:

1) The paragraph at the bottom of page 4 suggests that:

  "If the protocol mechanisms followed here are operating
   correctly, these features will only be among the set supported by the
   UAC. If that is not the case, the client SHOULD resubmit the request
   as if it were a 421 response."

   This seems somewhat dangerous to me. If the protocol features
   are not operating correctly, you must have a broken implementation
   somewhere. Under those circumstances, the inadvertant introduction
   of an undetected loop may occur. I'd suggest that the appropriate
   behavior for the client in this error situation would be:
   
    - For 1xx, CANCEL the call and be prepared to send a BYE.
    
    - For 2xx, ACK the response and then send a BYE.

    - For 300+, ACK the response and carry on as if the unsupported
      headers listed in the "Require" header are not present.

2) Under 4.2, it makes sense that a server should
   examine the "Required" headers as well. If a feature
   appears in the "Required" headers (but not in the "Supported"
   headers), it can assume that the client supports it.

   This comment applies elsewhere as well (e.g. the overview).

3) The otherwise innocuous attempt to negotiate features using 
   421 has the strong possibilty of being destroyed by intervening
   forking proxies. If my request forks at a proxy to two UAS nodes,
   there is the risk that one will return a response code of 400
   through 420. Since these are numerically lower than 421, they
   will be forwarded upstream, blocking out what may very well be
   a viable call leg from a UAS who attempts to ask for a particular
   feature.

   The only alternative I can propose without some pretty massive
   changes would be to revise your 421 response code to be something
   like 299. This response, of course, would be sent only in response
   to a request containing a "Supported:" header, so there's no
   risk of the client interpreting a 299 response as a generic
   "okay." You can consider it something of a conditional success
   message.

   Since this is a 200 class message, the forking proxy must
   terminate the search and forward the response upstream. The
   client re-launches the INVITE with the appropriate Supported/
   Unsupported headers; the second UAS is then free to service
   the call. One unpleasant side effect is that other clients
   who received forks may ring, stop, and start again as the
   extensions are negotiated. *But*, at least it maximizes the
   chances of terminating a call successfully.  (Can anyone think 
   of a better end around these problems? We could use a 1xx 
   response code, but since the provisional reliable draft relies 
   upon this one, we have something of a chicken-and-egg problem...
   We could overload the meaning of "400," but that seems horrible.)

4) In the message examples, the final message on page 7 (from A to B)
   contains no "Unsupported" header. This is consistent with the text.

   This leads to the strong possibility of loops. It doesn't seem
   too much of a stretch that some faulty code in the server,
   not seeing "com.dynamicsoft.foo" in either a "Supported" or
   "Unsupported" header may decide to once again query the client
   for its supported features. That response may contain only
   the "Unsupported: com.dynamicsoft.foo," without the
   "Supported: com.dynamicsoft.bar." You see how messy this could
   get.

   An easy way to reduce the chance of this would be to say the the 
   client MUST remember all the requested features until a (non-421)
   final response is received and include them in "Supported" and
   "Unsupported" headers in any subsequent INVITE messages. This is 
   very easy to implement.

5) Open issue 1: 

            "The current specification does not support extensions which
             require a proxy to modify responses as they travel along.
             This can probably be added without too much complexity. Is
             this a useful function?"

   Since we cannot predict whether such behavior
   will be useful in the future, I'd propose that it be added
   (since the document points out that such a negotiation can
   be done without too much complexity). It would be a shame to
   get to RFC and only then realise that there's a really cool
   service that we could have implemented if only...

6) Open issue 2: 

	    "Proxy-Require is not used; it doesn't seem necessary. It
             doesn't matter whether the endpoint generating a response
             is a proxy or UAS. Is that OK?"

   This seems okay. However, it does raise an
   interesting issue: if the server requires a feature that also 
   places requirements on the intervening proxies, does it
   indicate this fact explicitly, or is it the client's
   responsibility to know that the feature requires the
   cooperation of proxies? As an example, if the server wants
   reliable provisional responses (for whatever reason),
   and sends back a "Required: org.ietf.sip.100rel" header,
   does the client figure out that its next request needs to
   contain a "Proxy-Required: org.ietf.sip.100rel" header?
   
   Also, what if the server merely wants to place requirements
   on the proxies instead of the client?

7) Open issue 3: 

	    "Do we need the Require header in the final non-421 response
             to indicate what features were finally applied?"

   Yes. Absolutely, yes. The client may exhibit different behavior
   based on the set of features the server finally decides upon.
   Especially, for example, when there is no 421 involved. 
   I may indicate support of a particular feature in my INVITE, but
   without indication from the server, I don't know whether to
   exhibit the behavior required for that extension. Including
   the feature in a 200 even after negotiation is consistent with 
   this behavior (which simplifies implementation).

8) Open issue 4: 

	    "Should we remove org.ietf.sip.supported and have the
             presence of the Supported header alone indicate support for
             this extension?"

   I don't feel strongly one way or the other; if we were voting on
   it, I'd vote for removing the "org.ietf.sip.supported" and having
   the presence of "Supported" be sufficient. My rationale is that
   doing so would make the messages shorter, which is especially
   appropriate when using the "k:" header variant. It seems wildly
   inconsistent to jump through hoops like reducing "To:" to "t:" to 
   save a single byte, but requiring one to add the whole string 
   "org.ietf.sip.supported" (22 bytes -- probably more than you'll 
   save in an entire message by using compact headers) for a full 
   featured client.

-- 
Adam Roach, Ericsson Inc. |  Ph: +1 972 583 7594 | 1010 E. Arapaho, MS L-04
[email-masked]   | Fax: +1 972 669 0154 | Richardson, TX 75081 USA

---

From: Henning Schulzrinne <[email-masked]>
Date: Tue, 25 Jan 2000 20:40:57 -0500

Thanks for your detailed comments!

A few remarks:

>       headers listed in the "Require" header are not present.

Seems reasonable. Making failure explicit rather than just hoping that
things will work out also will make it much more likely that bugs like
these will be caught sooner rather than later.

>    This comment applies elsewhere as well (e.g. the overview).

Good idea. One would assume that features are symmetric, i.e., we don't
have "send-only" features where the client wants the server to
understand, say, a header, but has no clue what to do if it receives
that same header?

>    "okay." You can consider it something of a conditional success

Interesting. This seems apt if the server is prepared to fall back to
not using the feature. Kind of "I'd like to use this feature if possible
- you'll like it, but if you are dumb, the phone call must go through
and I'll take it if I have to". 

>    this behavior (which simplifies implementation).

Agreed.

>    save in an entire message by using compact headers) for a full

I made roughly the same argument...

-- 
Henning Schulzrinne   http://www.cs.columbia.edu/~hgs

---

From: "Adam B. Roach" <[email-masked]>
Date: Wed, 26 Jan 2000 08:40:28 -0600 (CST)

>and I'll take it if I have to". 

If something goes awry, yes... however, this won't be the normal
case. A server wouldn't be sending a 299 unless a Supported (or k)
header were present in the response. The presence of such a header
would necessarily indicate that the client understands the semantics
of the 299 message -- so a 299 arriving at a client who doesn't
know that it requires another INVITE indicates a faulty server
implementation (or a client who bizarrely sent a Supported header
without knowing what it meant).

---

From: Igor Slepchin <[email-masked]>
Date: Wed, 26 Jan 2000 15:45:25 -0500

"Adam B. Roach" wrote:
>    I'd suggest that the appropriate

It's theoretically possible for somebody to define an extension, say
com.foo.300is100 that completely redefines the meaning of response codes
and the default behavior may not be expected by the server when that
extension is used. However, I don't think we could do any better than
trying the above mentioned actions. After all, even the meaning of BYE
may be redefined.

>    "Unsupported" headers in any subsequent INVITE messages. This is

Wouldn't it be better to require the server to specify _all_ extensions
it may want to apply to the response in the Require header of the first
421 (in the above mentioned example, it would list both
com.dynamicsoft.foo and com.dynamicsoft.bar)? The client will then list
those it supports/does not support in the resubmitted request and the
server will be able to determine which ones it will actually use. It
will also save 1.5 round trip in the example.

---
Igor Slepchin

---

From: Henning Schulzrinne <[email-masked]>
Date: Wed, 26 Jan 2000 15:52:32 -0500

> trying the above mentioned actions. After all, even the meaning of BYE

Anything we can do to *dis*courage people redefining existing behavior
is probably a good idea, as this would seem to be the sure road to
interoperability hell.

> will also save 1.5 round trip in the example.

Given that the number of extensions is probably not dozens, I would
agree that a single indication is far simpler to manage than having them
be cumulative in some way. This goes along with the desire to make
things as stateless as possible and each message as self-contained as
possible.

---

From: "Adam B. Roach" <[email-masked]>
Date: Wed, 26 Jan 2000 15:04:05 -0600 (CST)

>things as stateless as possible and each message as self-contained as

Yes; I like this approach better as well. Since there seems to be
support for the point of view that the server sends back the finally
negotiated set of extensions in the final response, it can do its own
internal decision making at that time. I'll summarize what I understand
your proposal to be:

If a server wants to use com.dynamicsoft.foo, but com.dynamicsoft.bar 
would be an acceptable substitute (as in the draft), it would send 
back the 421 (or whatever we finalize) with a Require field specifying 
both. If the client indicates support for com.dynamicsoft.foo *and* 
com.dynamicsoft.bar, the server will include only com.dynamicsoft.foo 
in its final reply "Require" (thus indicating that com.dynamicsoft.bar
is not to be used).

---

From: Jonathan Rosenberg <[email-masked]>
Date: Wed, 26 Jan 2000 17:38:54 -0500

First off, thanks for your comments, Adam.

>       headers listed in the "Require" header are not present.

Whilst I agree with Igor that its possible that the feature overrides
the normal behavior of 300+, I agree with Henning this should be
discouraged. Since there is not much else you can do, I agree with Adams
approach.

>    This comment applies elsewhere as well (e.g. the overview).

I agree with others that this is a good idea.

>    We could overload the meaning of "400," but that seems horrible.)

I don't like this approach too much. The problem is that a 2xx response
to INVITE means the call is setup. Even though it should only be sent
when the client indicates it knows that 299 means otherwise, proxies
won't necessarily know. Thus, an intermediate proxy (say running a CPL)
which provides some kind of call forwarding service may get mightily
confused. Also, the 299 may begin billing in intermediate proxies which
run billing systems for gateways. The brief ring and cancellation is
also going to be annoying.

I'm not certain about the right solution. It requires some more thought.
Its broader than just 421; it applies to any response code which can
cause a request to be resubmitted with additional info (401 and 407 are
other examples).

> things as stateless as possible and each message as self-contained as

The problem I see here is that:

  1. the server may not know it might need to try bar until after it has
already asked for foo. The decisions about what features to apply may be
the result of programmatic execution after the resubmitted response.
Clearly, when it does know, what Igor suggested is fine (and probably
should be encouraged), but I don't want to mandate it. In that case, I
agree with Adam that the feature lists should be accumulated. We will be
doing this already for credentials, as described in Robert's multi-proxy
authorization draft.

  2. At this rate, we may well have dozens of extensions to SIP :(

>    service that we could have implemented if only...

Actually, I would argue the opposite for the same reason. Lets design
extensions that meet specific needs. Until someone comes up with a need,
I'd rather not build it into the protocol.

>    contain a "Proxy-Required: org.ietf.sip.100rel" header?

Yes. If the feature is supported, the client should know that if the
feature requires a request to be resubmitted, and this request needs
proxy support, the proxy-require header is needed. This is a bad
example, though, as the new 100 reliability draft doesn't actually
require proxies to understand it.  

>    on the proxies instead of the client?

Hmm. No way the mechanism supports this easily. Only clients can
resubmit requests. One way to do this would be to define a "stack"
header like Record-Route, and have each proxy push the set of features
it understands in the initial request. Seems overkill though, and can
lead to some very big messages. Might be other, more complex ways to do
this. 

Maybe its useful to list the various combinations of who wants who to do
what:

1. client needs proxies to understand feature to process request
2. client needs UAS to understand feature to process request
3. proxy needs downstream proxy to understand feature to process request
4. proxy needs UAS to understand feature to process request
5. UAS needs proxies to understand feature to process response
6. UAS needs UAC to understand feature to process response
7. proxy needs upstream proxies to understand feature to process
response
8. proxy needs UAC to understand feature to process response

I think that is every possible combination. (1) and (2) are covered by
require and proxy-require in the base spec. (6) and (8) are meant to be
covered by this draft. Can we identify needs for the others? 

Agreed. 

>    save in an entire message by using compact headers) for a full

I am leaning towards this also; seems Henning agrees also.

-Jonathan R.
-- 
Jonathan D. Rosenberg                       200 Executive Drive
Chief Scientist                             Suite 120 
dynamicsoft                                 West Orange, NJ 07052
[email-masked]                     FAX:   (732) 741-4778
http://www.cs.columbia.edu/~jdrosen         PHONE: (732) 741-7244
http://www.dynamicsoft.com

---

From: "Adam B. Roach" <[email-masked]>
Date: Wed, 26 Jan 2000 17:51:51 -0600 (CST)

>lead to some very big messages. Might be other, more complex ways to do

I beleive it can be acheived through very much the same mechanism
as is already defined in the draft.

For example, if I don't see a "Proxy-Require" header in the request
(but see a "Supported" header), I can send back a 421 with a
"Proxy-Require" header in it. The client then (regardless of whether 
it knows what the feature is) re-sends the INVITE with the Proxy-Require 
header mirrored in it.  If it gets a 420 back, it re-sends the request 
with a (new) "Proxy-Unsupported" header containing all of the features
indicated in the "Unsupported" header it got from the 420.  The server 
can use the "Proxy-Unsupported" header to determine which features the 
chain of proxies does not understand.  This adds no new requirements on 
proxies.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 27 Jan 2000 02:14:14 -0500

> chain of proxies does not understand.  This adds no new requirements on

This will only get you the set of features not supported by the first
proxy on the path that doesn't support at least one of the features
listed in Proxy-Require. Thats because the request with Proxy-Require is
rejected by the first proxy not supporting one of the features. You
won't learn about features not supported from servers downstream of that
one.

To be done correctly, either a stack mechanism must be used, or some
kind of set operations which cause proxies to add and remove features
from some specific headers in requests as they traverse the proxy path.
I'd still like to understand concrete applications before diving into
this; especially because interoperability begins to be tough when a
feature requires all proxies along the response path to understand it.

-Jonathan R.