Subject: [SIP] new record-route text!

From: Jonathan Rosenberg <[email-masked]>
Date: Fri, 29 Dec 2000 17:32:43 -0500

Folks,

I took a stab at the new text for record routing. Its much, much more
verbose than rfc2543, and hopefully, as a result, will make it much clearer
what you need to do. Record-routing remains one of the most oft
misimplemnted features. This text incorporates everything in rfc2543 plus
all the decisions we've made on the list along the way. As you can see, the
structure is much more processing focused, rather than syntactic focused,
and much more explicit as well.

The text is in latex format. If you don't know latex, you should be able to
ignore all the slashes and brackets and still get the idea.

Please comment; alternate text related to those comments is requested.

-Jonathan R.

\section{Record-Routing}
\label{sec:rr}

Record routing is the process whereby a proxy server can request to
receive all messages between two UAs for a 
particular call leg. The proxy accomplishes this by inserting a
header, called
\header{Record-Route} into the initial \INVITE request that begins the
call leg. The user agents use these headers to construct a set of
\header{Route} headers, that gets inserted into subsequent requests in
the call leg. The \header{Route} headers contain a set of proxies that
the request must visit on its way from one UA to another. Proxies use
these to forward the requests, much like strict IP source routing.

All user agents \MUST support the processing rules below which apply
to them. As such, they \MUST be able to parse and process both
\header{Record-Route} and \header{Route} headers. Proxies \MAY support
the record routing procedures of Section \ref{sec:rr:proxy}, but they
\MUST support the route header procedures of Section{sec:rr:proxy2}. 

\motivation{This is a change from RFC2543, where all record-route and
route processing was optional for user agents.}

The syntax for the \header{Route} header is described in Section
XXX. The syntax for the \header{Record-Route} header is described in
Section XXX.

\subsection{UAC Processing for initial \INVITE transaction}
\label{sec:rr:uac}

The UAC formulates its {\em initial} \INVITE request for the call leg
as defined in section XXX. If the final response is a 200 class
response, it may contain \header{Record-Route} headers, and may
contain a \header{Contact} header. \annotate{Contact was not mandatory
in RFC2543. Thus, if the UAC is talking to an older UAS, the UAS might
not insert the \header{Contact} header. Thats why this text says that
the \header{Contact} may be present in the response. Note also that
this may is lower case; it is NOT saying that a UAS can optionally
insert the \header{Contact} header into the 200 class response.} The
UAC \MUST construct a {\em route set}, defined as a list of URLs, in
the following manner:

\begin{enumerate}
\item The list of URIs present in the \header{Record-Route} headers in
the 200 class response are taken, if present, and their order is reversed. 
\item The URI in the \header{Contact} header from the 200 class response, if
present, is taken, and appended to the end of the list from the
previous step.
\item The list of URIs resulting from the above two operations is
referred to as the {\em route set}.
\end{enumerate}

The UAC \MUST store the route set for the duration of the call
leg. NOTE that it is possible for the route set to be empty. This will
occur if neither \header{Record-Route} headers nor a \header{Contact}
header were present in the 200 class response. NOTE that since there
may be multiple 200 OK responses to an \INVITE request, each response
constitutes a separate call leg, and thus has a separate route
set. The UAC \MUST also remember whether the bottom-most entry in the
route set was constructed from a \header{Contact} header or not. This
is effectively a boolean value, which we refer to as CONTACT_SET.

The \ACK request for the initial \INVITE transaction \MUST be
formulated according to the rules of Section XXX, as if it were a
subsequent request within the call leg. 

OPEN-ISSUE: Handling for non-200 responses, including provisionals
and certain 400 class responses. Are we supporting record-routing for
non-200 class responses? Record-routing for provisional responses is
discussed in the 100rel spec. What needs to be said here?

\subsection{UAS Processing of initial \INVITE transaction}
\label{sec:rr:uas}

When a UAS receives an \INVITE for a new call leg, and it responds
with a 200 class response, it \MUST copy the contents of the
\header{Record-Route} headers from the request to the response. This
includes the URIs, URI parameters, and any \header{Record-Route}
header parameters, whether they are known or unknown to the
UAS. \annotate{Record-Route parameters are very useful for
proxies. They allow the proxy to match the record-route entry in the
response with the one in the request.} The
order of the \header{Record-Route} headers \MUST be preserved in the
response.

The UAS \MUST construct a {\em route set} in the following manner:

\begin{enumerate}
\item The list of URIs in the \header{Record-Route} headers in the
\INVITE request, if present, are taken, including any URI parameters.
\item The URI in the \header{Contact} header from the request, if present,
is
taken, including any URI parameters. The URI is appended to the bottom
of the list of URIs from the previous step.
\item The resulting list of URIs is called the {\em route set}. 
\end{enumerate}

The UAS \MUST store the route set for the duration of the call
leg. NOTE that it is possible for the route set to be empty. This will
occur if neither \header{Record-Route} headers nor a \header{Contact}
header were present in the \INVITE request. The UAS \MUST also
remember whether the bottom-most entry in the route set was
constructed from a \header{Contact} header or not. This is effectively
a boolean value, which we refer to as CONTACT_SET. 

OPEN ISSUE: this new text does not have the record-routes copied into
non-200 responses. RFC2543 talks about other failure codes, but is not
specific enough. Do we really need them in other response codes? If
so, we must list them explicitly.

\subsection{Proxy processing of an initial \INVITE transaction}
\label{sec:rr:proxy}

Each proxy \MAY independently decide to record-route an initial
\INVITE transaction. For a proxy, {\em initial} is defined
as any \INVITE request that does not contain a \header{Route}
header. Generally, the choice about whether to record-route or not is
a tradeoff of features vs. performance. Faster call processing and
higher scalability is achieved when proxies do not record
route. However, provision of certain services may require a proxy to
observe all messages for a call leg. It is \RECOMMENDED that proxies
do not automatically record route. They should do so only if
specifically required.

To record-route, the proxy inserts a \header{Record-Route} header into
the request before proxying it onwards. A forking proxy \MAY insert a
different \header{Record-Route} header into each forked request. The
\header{Record-Route} header that it inserts \MUST be inserted as the
first \header{Record-Route} header, appearing before any existing ones
in the request. The URL in the header \MUST be a SIP
URL. \annotate{This is because the URLs in the Record-Route headers
are used for forwarding requests by other proxies. Since no other URL
but a SIP URL is mandatory, a proxy could not be sure that any other
URL is interpretable by other proxies. Thus, SIP URLs are
mandatory}. The URL \MUSTNOT contain the transport
parameter. \annotate{Thats because only UDP is mandatory. If a proxy
inserts a transport parameter in the URL with TCP or TLS as the
transport, the proxy that ends up using that URL to forward the
request might not support that transport. The result, according to the
``Locating a SIP Server'' procedure, would be for the proxy to give
up.} The URL \MUST have the property that when the processing
described in Section XXX ``locaing a SIP server'' is followed for that
URL, the result of the lookup is an address/port of the proxy server
inserting the
\header{Record-Route}. The URL and the proxy configuration \SHOULD be
such that if a request is received with this URL in the
\header{Request-URI}, the proxy's normal request processing will cause
it to be forwarded to one of the previous-hop servers that the initial
\INVITE request traversed, including the UAS. \annotate{These two
properties are 
important. The first one guarantees that subsequent requests from the
called party are routed back to this actually proxy. The second property is
there for robustness. It guarantees that the request URI always
contain meaningful information, even if there are no \header{Route}
headers that tell the proxy where to forward the request to next.} The
proxy \MAY insert 
\header{Record-Route} parameters into the request. These will be
returned to the proxy in any 200 class response to the \INVITE, and
are useful for pushing state into the message.

If a 200 class response arrives for a proxied request, the response
will contain the entire list of \header{Record-Route} headers inserted
by proxies along the request path. The proxy \MAY modify the
\header{Record-Route} value matching the one it inserted into the
request. Like the URL in the request, it \MUST be a SIP URL and
\MUSTNOT contain a transport parameter. The URL in this
\header{Record-Route} header \MUST have the
property that when the processing described in Section XXX ``locating
a SIP server'' is followed for that URL, the result of the lookup is
an address/port of the proxy server that inserted the
\header{Record-Route}. The URL in this header, and the proxy configuration
\SHOULD be
such that if a request is received with this URL in the
\header{Request-URI}, the proxy's normal request processing will cause
it to be forwarded to the same next hop server that the initial
\INVITE request was forwarded to.

The four properties (two for the request, two for the response), can
be satisfied in a number of ways. One way is that the URI inserted
into the \header{Record-Route} in the request is the same as the
\header{Contact} header in the \INVITE (if present, else the
\header{From} field), but with the maddr and port set to
resolve to the proxy. Then, the proxy modifies the URL in the
\header{Record-Route} header in the response, setting it to be the URL
from the \header{Request-URI} of the initial \INVITE, but with the maddr
and port set to resolve to the proxy. 

As an example, consider a proxy at 10.0.1.1 listening on port 5061
which receives the following request (many headers are omitted for
brevity):

\begin{verbatim}
INVITE sip:[email-masked] SIP/2.0
Via: SIP/2.0/UDP callerspc.univ.edu
Contact: sip:[email-masked]
\end{verbatim}

The proxy forwards this request to
\header{sip:[email-masked]}, and record-routes:

\begin{verbatim}
INVITE sip:[email-masked] SIP/2.0
Via: SIP/2.0/UDP 10.0.1.1:5061
Via: SIP/2.0/UDP callerspc.univ.edu
Record-Route:
 <sip:[email-masked]:5061;maddr=10.0.1.1>
Contact: sip:[email-masked]
\end{verbatim}

The 200 response will look like, in part:

\begin{verbatim}
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.0.1.1:5061
Via: SIP/2.0/UDP callerspc.univ.edu
Record-Route:
 <sip:[email-masked]:5061;maddr=10.0.1.1>
Contact: sip:[email-masked]
\end{verbatim}

The proxy modifies its \header{Record-Route} header in the response to
and forwards the request upstream:

\begin{verbatim}
SIP/2.0 200 OK
Via: SIP/2.0/UDP callerspc.univ.edu
Record-Route:
 <sip:[email-masked]:5061;maddr=10.0.1.1>;myparam=9877
Contact: sip:[email-masked]
\end{verbatim}

The route set computed by the UAS is:

\begin{verbatim}
sip:[email-masked]:5061;maddr=10.0.1.1
sip:[email-masked]
\end{verbatim}

and the route set computed by the UAC is:

\begin{verbatim}
sip:[email-masked]:5061;maddr=10.0.1.1
sip:[email-masked]
\end{verbatim}

There are other ways to meet these requirements. The proxy could
construct a URL for the request which encodes all of the needed
information, by placing it in the user portion, for example. A call
stateful proxy could insert a URL into the request with the form
sip:proxy.example.com, and not modify it in the response. This URL
clearly satisfies the first required property (of getting routed back
to the proxy that inserted it). The second property can be maintained
by being call stateful, and extracting the needed parameters from
local storage.

When a proxy does decide to modify the \header{Record-Route} header in
the response, one of the operations it must perform is to locate the
\header{Record-Route} that it had inserted. If the request spiraled,
and the proxy inserted a \header{Record-Route} in each iteration of
the spiral, locating the correct header in the response (which must be
the proper iteration in the reverse direction) is tricky. One
mechanism that is \RECOMMENDED is for the proxy to insert a
\header{Record-Route} parameter into the new \header{Record-Route} header
in the request each time the request spirals. This parameter \MUST
uniquely identify the proxy. When the 200 class respone arrives, the
proxy looks for the topmost \header{Record-Route} header containing
this parameter. This header is the one for the current iteration. The
proxy \MUST remove this parameter before forwarding the response
upstream. Upon the next iteration, the same algorithm (find the
topmost \header{Record-Route} header with the parameter) will
correctly extract the next \header{Record-Route}
header.

\subsection{UA Processing of Subsequent Requests in a Call Leg}
\label{sec:rr:uasubsequent}

When a UA wishes to send another request for the call-leg (such as a
\header{BYE} or \header{INVITE}), it follows the procedures defined in
this subsection. The
procedures here \MUST also be followed for an \ACK request for a 200
response to the initial \INVITE for the call leg. The procedures here
\MUSTNOT be followed for a \CANCEL request or an \ACK request for a
non-200 response. This implies that \CANCEL never contains a
\header{Route} header, nor does an \ACK for a non-200 response.

The request is constructed as specified in Section XXX. The UA then
takes the list of URI in the route set. The top URI is inserted into
the request URI of the request, including all parameters. Any URI
parameters not allowed in the request URI \MUST then be stripped. Each
of the remaining URIs (if any) from the route set, including any
URI parameters, are placed into a \header{Route} header into the request,
in order. The procedures of Section XXX ``locating a SIP server'' are
then applied to the URI in the request URI, the the request is
forwarded to the resulting server.

If a UAS has a route set for a call leg, and receives a re-INVITE for
that call leg containing \header{Record-Route} headers, it \MUST copy
those headers into any 200 class response to that request. If the
boolean variable CONTACT_SET is true, the \header{Contact} header in
the re-INVITE (if present) replaces the last 
entry in the route set. If the boolean variable CONTACT_SET is false,
the UAS \MUST add the URL in the 
\header{Contact} header in the re-INVITE to the bottom of the route
set, and then set CONTACT_SET to true. If the re-INVITE did not
contain a \header{Contact} header, the route-set at the UAS remains
unchanged.

Similarly, if a UAC has a route set for a call leg, and receives a 200
class response to a re-INVITE it sent, the \header{Contact} header is
examined. If not present, the route set remains unchanged. If the
re-INVITE response had a \header{Contact} header, and the boolean
variable CONTACT_SET is false, the URL in the \header{Contact} header
in the response is added to the bottom of the route set, and
CONTACT_SET is set to true. If the re-INVITE response had a
\header{Contact} header, and CONTACT_SET is true, the URL in the
\header{Contact} header of the re-INVITE response replaces the bottom
value in the route set.

The above two paragraphs allow a UA to update its \header{Contact}
address mid-call, but proxies cannot update their route address.  Once
on the route, a proxy remains on the route for the duration of the
call leg. \annotate{Why the different treatment for Contact and
Record-Route in a re-INVITE? It has to do with backwards
compatibility. RFC2543 did not mandate that a proxy needs to refresh
its record-route headers. As a result, the lack of a record-route in a
re-INVITE cannot be interpreted to mean that the proxy does not want
to be included on the route any longer. Updating of the Contact header
mid-call is useful for mobility applications, and is also useful for
forms of third party call control}.

OPEN-ISSUE: should the UA remove the maddr param, if present, if the
request is sent to the server at that maddr?

OPEN-ISSUE: should we mention handling of route with local outbound
proxies here? RFC2543 has some text on DNS-less UAs, but there are
issues with this.

\header{Proxy processing of a non-initial request}
\label{sec:rr:proxy2}

The rules in this section \MUST be followed when a proxy receives a request
that contains a \header{Route} header. The \header{Route} header is
used to forward the request to the next hop. It \MUST override any other
routing decisions that the proxy would otherwise make. Proxies \MAY
respond to requests with \header{Route} headers for any reason (in order
to perform proxy authorization, for example). But, if the request is
proxied, the procedures here \MUST be used to determine where the
request is proxied to. The procedures in this section apply indepedent
of the request method. They \MUST be followed even if the request
method is unknown to the proxy. \annotate{This last sentence is
really, really important. It allows for other methods, defined in the
future, to have record-routing applied to them. As an example, an
instant messaging session run over SIP might begin with a MESSAGE
request. That extension can allow for these sessions to be
record-routed by proxies that know of this extension. However, the
record-routing will only work if proxies that don't know about the
extension follow the Route headers properly. As such, supporting
\header{Route} headers for all methods, known or unknown, is very
important for a robust and future proof proxy implementation.}
Since \CANCEL can never contain
\header{Route}, these procedures never apply to \CANCEL. However, they
do apply to \ACK requests for a 200 OK response, which do contain
\header{Route} headers. 

The proxy \MUST remove the top \header{Route} header from the
request. The URI from that \header{Route} \MUST be placed into the
\header{Request-URI} of the proxied request, including URI
parameters. Any URL parameters present in the top \header{Route}
header which are not allowed in the request URI \MUST be removed from
the \header{Request-URI} by the proxy. The procedures of section XXX
``Locating a SIP Server'' \MUST be followed to compute the next hop
server to forward the request to. 

If the request is an \INVITE request (thus, a re-INVITE) for a call
leg that the proxy wishes to receive messages for (very likely the
case, since the request probably arrived at the proxy because the
proxy record routed in the initial \INVITE), the proxy \MUST
re-insert the
\header{Record-Route} header with the same value it placed in the
initial request. Similarly, it should modify the \header{Record-Route}
header in any 200 class response in the same way the
\header{Record-Route} header was modified in the response to the
initial \INVITE (which may be no modifications at all). The purpose of
this is twofold. First, it allows for proper record-routing in the
case of pre-loaded Route headers (see Section XXX). Secondly, it
allows for recovery from a UA crash and restart, in which case the UA
loses call state, and as a result, its route set as well. The result
is that the route set will be re-established through the
re-INVITE. When coupled with the Session Timer \cite{RFCXXX}, the
result is a robust way to recover from crashes.

\subsection{Pre-Loaded Route Headers}

Normally, a UA constructs the Route headers in a request from the
route set learned through \header{Record-Route} headers. However, in
some circumstances, it is useful for a UA to insert \header{Route}
headers into an initial \INVITE. These headers may have been learnt by
the UA through some out of bands means. When an initial \INVITE
(initial as far as the UAC and UAS are concerned) contains
\header{Route} headers, this is referred to as a ``pre-loaded
Route''. It is equivalent to strict source routing in IP. Proxies will
often not be able to distinguish this case from the case described in
Section \ref{sec:rr:proxy}, and will therefore properly use these
route headers to forward the request. If the proxies are interested in
receiving subsequent messages for the call leg, their insertion of
\header{Record-Route} as mandated by Section \ref{sec:rr:proxy} will
establish a correct route set at both UAC and UAS. This route set may
end up being different from the pre-loaded Route used by the UAC. As
such, a UAC that inserts a pre-loaded route set \MUST follow the
procedures of Section \ref{sec:rr:uac} in processing the response to
this initial \INVITE.

---
Jonathan D. Rosenberg                       72 Eagle Rock Ave.
Chief Scientist                             First Floor
dynamicsoft                                 East Hanover, NJ 07936
[email-masked]                     FAX:   (973) 952-5050
http://www.cs.columbia.edu/~jdrosen         PHONE: (973) 952-5000
http://www.dynamicsoft.com

_______________________________________________
SIP mailing list
[email-masked]
http://lists.bell-labs.com/mailman/listinfo/sip

---

From: Henning Schulzrinne <[email-masked]>
Date: Fri, 29 Dec 2000 22:35:16 -0800

# Comments are marked thusly; not meant as text.

# In general, some of the Route stuff needs to be copied or moved in the
general discussion of request routing. I'd like to keep those core rules
in one place rather than having to hunt around for all the different
decisions on where to send things.

> \section{Record-Routing}

# This should state what we're trying to accomplish, not the means,
e.g.,

\section{Forcing Request Routes}

> \label{sec:rr}

# adding motivation and context

By default, all but the first request within a call leg are exchanged
directly between the UAC and the UAS. However, in some circumstances,
some proxies may need to process all requests within a call leg, not
just the first one. This is accomplished by a set of SIP header fields
and processing rules for proxies, UAS and UAC. We will refer to this set
of rules as ``record-routing''.

> receive all requests between two UAs for a

# changed from messages to requests, since responses don't need this
mechanism

> particular call leg. The proxy accomplishes this by inserting a

header field

> \header{Route} headers, that gets inserted into subsequent requests in

that the UAC inserts into

> the call leg. The \header{Route} headers contain a set of proxies that

header fields list the URLs of proxies

> these to forward the requests, much like strict IP source routing.

Proxies use these URLs 

> XXX. The syntax for the \header{Record-Route} header is described in

# Something should be said here about non-INVITE requests, if only to
answer the obvious question, e.g.

The record-routing mechanism only applies to {\INVITE} transactions.
Inserting \header{Record-Route} in requests other than {\INVITE} is
{\NOTALLOWED}.

# Some overview of the cases below, e.g.,

Below, Section~\ref{sec:rr:uac} discusses how UAC process the first
{\INVITE} request within a call leg. Section ...

# probably should group sections below into initial and subsequent
requests

# remainder omitted for later

---

From: Billy Biggs <[email-masked]>
Date: Sat, 30 Dec 2000 23:20:27 -0500

RR for non-INVITE call legs and non-INVITE requests, part 1:

  For me, a call-leg is created equally for all requests.  The final
  response completes the leg and establishes the Route and tags.  This
  moves the request from the one-to-many state to a one-on-one call.

  My implementation of SUBSCRIBE/NOTIFY is no different.  NOTIFYs
  follow the established Route back and use the tags, and NOTIFYs
  received which do not match the established legs tags are 481'd.

  Your proposal seems to be that any request other than INVITE cannot
  create a call leg, and that the NOTIFY be sent strictly to the
  Contact address, not follow the Route, and reset the tags.

  That's a big switch.  I'm sure everyone who has implemented (at
  least) SUBSCRIBE/NOTIFY will have to change their code.

  This also means that any firewall proxy MUST mangle the Contact
  address for all outgoing requests other than INVITE.  (Note that if
  the Contact address on an INVITE is mangled, it MUST NOT be to a
  redirect server, since this means we get mid-call redirects, which
  don't work).

RR for non-INVITE call legs and non-INVITE requests, part 2:

  RR/Route must be allowed for non-INVITE requests within a call, such
  as REFER.  This of course makes the logic really weird, since the
  behavior for non-INVITE requests outside of a leg is different than
  those within.

-- 
Billy Biggs                     [email-masked]
http://www.billybiggs.com/      [email-masked]

---

From: Billy Biggs <[email-masked]>
Date: Sun, 31 Dec 2000 09:40:18 -0500

> request is sent to the server at that maddr?

  No, since the request may be snarfed by a transparent proxy.  maddrs
should never be stripped from the RURI (unless of course by the host
represented in the maddr).

> proxies here? RFC2543 has some text on DNS-less UAs, but there are

  Route handling does not change if you have a local outbound proxy.
With an outbound proxy configured, outgoing messages should be
unchanged: all processing remains the same.  The difference is that
requests are IP'ly sent to a specific address.

> OPEN-ISSUE: Handling for non-200 responses, including provisionals and
> certain 400 class responses. Are we supporting record-routing for

  I'm for disallowing RR'ing of non-200s.