Making SIP HTTP/1.1 Compliant

Yaron Goland <yarong@microsoft.com> Tue, 28 April 1998 08:14 UTC

Return-Path: <owner-confctrl>
Received: (from majordom@localhost) by zephyr.isi.edu (8.8.7/8.8.6) id BAA27807 for confctrl-outgoing; Tue, 28 Apr 1998 01:14:51 -0700 (PDT)
Received: from tnt.isi.edu (tnt.isi.edu [128.9.128.128]) by zephyr.isi.edu (8.8.7/8.8.6) with ESMTP id BAA27802 for <confctrl@zephyr.isi.edu>; Tue, 28 Apr 1998 01:14:50 -0700 (PDT)
Received: from mail4.microsoft.com (mail4.microsoft.com [131.107.3.29]) by tnt.isi.edu (8.8.7/8.8.6) with ESMTP id BAA19964 for <confctrl@isi.edu>; Tue, 28 Apr 1998 01:14:49 -0700 (PDT)
Received: by INET-04-IMC with Internet Mail Service (5.5.1960.3) id <JVK7JA95>; Tue, 28 Apr 1998 01:14:50 -0700
Message-ID: <3FF8121C9B6DD111812100805F31FC0D02971261@red-msg-59.dns.microsoft.com>
From: Yaron Goland <yarong@microsoft.com>
To: "'confctrl@isi.edu'" <confctrl@ISI.EDU>
Subject: Making SIP HTTP/1.1 Compliant
Date: Tue, 28 Apr 1998 01:14:47 -0700
X-Mailer: Internet Mail Service (5.5.1960.3)
Sender: owner-confctrl@zephyr.isi.edu
Precedence: bulk

3 Making SIP HTTP/1.1 Compliant

HTTP does not have a lot of mandatory requirements. Requirements in HTTP are
generally written in the form "If you support this feature then you MUST do
the following." However if you don't support the feature then no action is
required.

For example, Scott Lawrence from Agranat was telling me that he has a fully
functioning 100% compliant extremely HTTP/1.1 server that is 24k long. He
imbeds it in things like printers.

The biggest misconception I ran into when talking to people involved with
SIP is that being HTTP/1.1 compliant meant having to support GET and PUT or
the other HTTP/1.1 methods. This is not the case. There is no requirement in
HTTP/1.1 to support ANY methods. So a SIP HTTP/1.1 server would ONLY support
SIP methods.

Below I have listed the minor additions needed to make SIP clients and
servers HTTP/1.1 compliant. Proxies become compliant when they meet the
requirements for both clients and servers.

3.1 New Client Requirements

3.1.1 Chunked Transfer

Clients must be able to receive chunked transfers. They do not have to be
able to send them. A chunked transfer is basically a series of length
encoded strings. They are used when the server is sending dynamic data.

The following algorithm taken from section 19.4.6 of the latest HTTP/1.1
draft describes how to decode a chunked transfer:

length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
	read chunk-data and CRLF
	append chunk-data to entity-body
	length := length + chunk-size
	read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
	append entity-header to existing header fields
	read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding

3.1.2 Host Header

HTTP/1.1 requires the use of the HOST header with every request. If you
switch to HTTP/1.1 you will be using HTTP URLs in the request-URI anyway so
supporting HOST is trivial. For example, if you are communicating with
http://sipserver/jake then the request-URI becomes /jake and the host header
is Host: sipserver.

Note, BTW, as I specify below, that you can still use a SIP URL in the
request-URI, if you want to. I advise against it but it is legal.

3.2 New Server Requirements

3.2.1 Chunked Transfer

HTTP/1.1 servers are not required to be able to receive chunked transfers
but they MUST be able to recognize that someone is sending them a chunked
transfer and fail the request properly. To do this the server needs to
recognize the transfer-encoding header and at the most basic, fail any
request that contains it.

3.2.2 Host Header

Obviously if HTTP/1.1 clients are sending Host headers the server needs to
be able to receive them.

3.3 SIP Protocol Changes

3.3.1 4.3 Request-URI

3.3.1.1 Compliance Requirement

It is legal in HTTP/1.1 to use arbitrary URLs in the request-URI of a
message. For example, the following is a legal request:

GET ftp://server/file HTTP/1.1

An FTP enabled proxy will make an FTP DIR request and then return the result
formatted in HTML.

So if SIP wishes to use SIP URLs in the request-URI that is just fine.
However they will always have to use the full SIP URL form in order to
prevent confusion with HTTP URLs.

3.3.1.2 Mapping to HTTP

However I would suggest that SIP consider providing a mechanism to translate
a SIP URL into an HTTP URL and then using the HTTP URL in the request-URI.

The motivation for this suggestion is the desire to make SIP able to take
advantage of the currently deployed HTTP proxies, both 1.0 and 1.1.

The reason that using a SIP URL in the request-URI is a problem is that an
HTTP proxy wouldn't know where to send the request. For example:

INVITE sip://joe@nowhere.com HTTP/1.1
From: sip://mike@somewhere.org
To: sip://joe@nowhere.com

If a proxy receives this, knowing nothing about SIP, it can't do anything
but refuse the request. It can't even tunnel the request.

But imagine if instead the same proxy were to receive:

INVITE / HTTP/1.1
Host: nowhere.com
From: sip://mike@somewhere.org
To: sip://joe@nowhere.com

The proxy won't know what an INVITE method is or what the From or To headers
are. However proxies do know what to do when they don't know what to do,
they turn themselves into tunnels. The proxy will read the Host header and
realize that the message is meant to be delivered to "/" at nowhere.com.
Thus currently deployed HTTP proxies can properly tunnel through the
request.

3.3.1.3 Expanding the SIP URLs

It would be even cooler if one could take advantage of the HTTP namespace
from within a SIP URL. This would be accomplished by expanding the
definition of the SIP URL such that it allows URLs of the form
sip://mike@somewhere.org/mikesphone.

This would be translated into the HTTP URL http://somewhere.org/mikesphone.
Note that currently specified SIP URLs will work just fine. For example,
sip://bobby@ooga.boo would translate into http://ooga.boo/.

So adopting this translation convention will work just fine with SIP URLs as
they are defined today and allows SIP URLs to access the full HTTP
namespace. A no lose proposition.

3.3.1.4 Tunneling to a SIP Proxy

Imagine mike@somewhere.org, wants to send an INVITE to
sip://joe@nowhere.com. Furthermore, mike knows there is a SIP proxy at
http://sipproxy.com/proxy. However there is a problem, the client has a
normal HTTP firewall between him and sipproxy.com.

At this point mike could just send the following message:

INVITE http://nowhere.com/ HTTP/1.1
Host: nowhere.com
From: sip://mike@somewhere.org
To: sip://joe@nowhere.com

The HTTP/1.1 proxy will properly forward it on to nowhere.com. However there
might not even be a nowhere.com! After all, the address hasn't had a chance
to go through the SIP resolution process to find out what the REAL address
is for joe@nowhere.com.

So what can we do? Mike needs to talk to his SIP proxy but he can't get
through his firewall. Or can he?

The really cool thing about adopting HTTP URLs for the request-URI is that
Mike could send the following message:

INVITE http://sipproxy.com/proxy HTTP/1.1
From: sip://mike@nowhere.com
To: sip://joe@somewhere.com

Bam! The request goes through his HTTP/1.1 proxy to his SIP proxy at
http://sipproxy.com/proxy and gets properly handled. Joe gets his invite and
everyone wins.

Now, you can't tell me that isn't cool. =)

3.3.2 4.3.1 SIP Version

Obviously the SIP/2.0 version information would have to be changed to
HTTP/1.1.

3.3.3 4.4 Option Tags, 6.26 Proxy-Require, 6.27 Require

If you switch to HTTP/1.1 you won't have to solve this problem on your own.
Rather you can leverage the work of Henrik Frystyk in his soon to be
standardized Mandatory draft available at
http://www.ietf.org/internet-drafts/draft-frystyk-http-mandatory-00.txt

Note that the Mandatory header provides both end to end and hop by hop
functionality so it can handle both the proxy-require and the require
headers.

3.3.4 6.20 Location

The Location header is specified by HTTP although you have changed it in a
way that is not compatible. Given the experience with TCN (Transparent
Content Negotiation) I think you will find specifying q values a total waste
of time. I don't know what it is about q values that everyone feels a need
to invent them. Repeated deployments have convinced me that they add nothing
but complexity.

As such you can easily move back to the normal HTTP Location header and
simply specify that entries should be listed in order of preference. If our
experience with q values doesn't apply (and I'm willing to bet bucks it
does) then just change the name from Location to Sip-Location or something
and you're compliant.

3.3.5 6.38 Via

HTTP's Via header and SIP's differ on a number of points.

3.3.5.1 Removing the Via Header on Response Paths

HTTP does not remove the VIA header. The reason for this, as I explain in
some detail in a similarly titled section in the general comments section,
is that the information is needed by clients for debugging and path
capability determination. The later feature being critical in a
multi-version protocol environment.

As such, in order to be HTTP compliant, SIP needs to strike its rule
regarding removing Via headers.

However, as I argue in the previously cited section, this action, far from
being a compromise, is in SIP's interest.

3.3.5.2 Order of Via Headers

In SIP the Via headers are like a stack, where each new proxy pushes its Via
header on the top.

In HTTP the Via headers are a list where each new proxy appends its Via
header.

The result is that SIP and HTTP use the reverse orderings of the other.

To be HTTP compliant SIP would need to reverse its ordering.

While I realize that SIP choose its ordering for performance reasons I would
suggest that any performance gains are most likely illusory. The reason
being that at every hop the proxy or server must check all the headers in
the message, not just Via. Thus the entire message must be parsed. This
makes the ordering selection, whether HTTP's or SIP's, irrelevant as the
cost of processing the entire message must be born regardless.

3.3.5.3 Received Attribute

As far as I can tell the purpose of the received attribute is not to prevent
loops but to help UDP SIP servers remain stateless. Specifically, a UDP SIP
server needs to know where to send the response. In the case where the
downstream proxy, which sent the request to the UDP SIP server, uses a
hidden server name or an incorrect IP address, the UDP SIP server needs to
remember the correct IP address to send the response to. As such the
received attribute is appended to the Via header as a way of "jotting down"
the return address. Hence if the UDP SIP server has to make requests of its
own in order to fulfill the request it doesn't need to remember the original
IP address it has to send the response to. Instead, when a response finally
arrives, the UDP SIP server can just check the received attribute in the Via
header and know where to forward the response to.

Unfortunately there is no reliable way to record the receive information in
the HTTP Via header. We could, in theory, put it into the comment field but
this won't work because any proxy along the processing path can remove
comments.

As such, in order to be HTTP compliant, SIP must make a compromise. The
compromise is that it needs to add a new header I call "memory". The format
of the header would be:

Memory = "memory" ":" 1#(sent-by ";" host [":" port])

This header records the sent-by name used in the via header and associates
it with an IP address and port.

I realize that this solution is not nearly as efficient, in terms of time or
space, as putting the information in the Via header. However that is simply
not possible in HTTP. I believe that this is a reasonable trade-off in order
to gain the benefits of being HTTP compliant.

3.3.5.4 TTL & Hidden

I don't understand why TTL is included in the Via header. Can someone
explain this to me please?

The same goes for hidden. I don't fully understand its purpose so it is
difficult to come up with a way to move it to HTTP.

3.3.6 6.39 Warning & 7.6.4 606 Not Acceptable

The BNF for your warning header along with its functional description
appears to be compliant with HTTP. However the way you actually use it in
the spec is not. The warning code format is not compatible since HTTP (and
your own BNF) use two digit codes while SIP uses a xxx.x format.

In order to be HTTP compliant you will either have to translate the xxx.x
codes to two digit warning numbers or not use the warning header and instead
create new 6xx errors for what you now call warnings. I would suggest
creating new errors.

Alternatively you can define a new header for use with 606 which provides
the information you tried to provide through warnings.

3.3.7 7.6 Global Failures 6xx

HTTP was designed for point to point communications but you legitimately
have expanded the boundaries. I know that the Microsoft proxy, if it
received a 6xx response number, would just pass it through without caching.
Assuming no serious problems with proxies I think you have given legitimate
reason to add a new response code series, 6xx.

3.3.8 SIP Header

I would recommend you create a new header called the "SIP" header that is to
be returned in OPTIONS responses by SIP compliant servers. This way I can
walk up to an HTTP/1.1 server and ask it "Do you support SIP?". This is NOT
a requirement to be HTTP/1.1 compliant but is probably a good idea.

3.4 Unnecessary Sections

If SIP moves over to HTTP/1.1 then the following sections can be removed:
1.4, 1.5, 5, 6.1 - 6.10, 6.12, 6.13, 6.15, 6.17, 6.21, 6.24, 6.25, 6.31,
6.32, 6.37, 6.40, 7.2, 7.3.1 - 7.3.3, 7.4.1 - 7.4.9, 7.5, 8, C