\section{Behavior of SIP Proxy Servers}
\label{sec:searching}

This section describes behavior of SIP proxy servers in detail.  Proxy
servers can ``fork'' connections, i.e., a single incoming request spawns
several outgoing (client) requests. 

A proxy server can either be stateful or stateless.  When stateful, a
proxy remembers the incoming request which generated outgoing requests,
and the outgoing requests.  A stateless proxy forgets all information
once an outgoing request is generated.  A forking proxy {\MUST} be
stateful.  Proxies that accept TCP connections {\MUST} be stateful when
handling the TCP connection.  A proxy sending a request out to a
multicast address {\MUST} be stateful.

\motivation{Otherwise, if the proxy were to lose a request, the TCP
client would never retransmit it.}

A stateful proxy {\SHOULDNOT} become stateless until after it sends a
definitive response upstream, and at least 32 seconds after it received a
definitive response.
 
A {\em stateful} proxy acts similar to a virtual UAS/UAC, but cannot be
viewed as just a UAS and UAC glued together at the back.  (In
particular, it does not originate requests except {\ACK} and {\CANCEL}.)
It implements the server state machine when receiving requests, and the
client state machine for generating outgoing requests, with the
exception of receiving a 2xx response to an {\INVITE}.  Instead of
generating an {\ACK}, the 2xx response is always forwarded upstream
towards the caller.  Furthermore, {\ACK}'s for 200 responses to
{\INVITE}'s are always proxied downstream towards the UAS, as they would
be for a stateless proxy. 
 
A {\em stateless} proxy forwards every request it receives downstream,
and every response it receives upstream. 

\subsubsection{Proxying Requests}
\label{sec:proxying}

A proxy server {\MUST} check for forwarding loops before proxying a
request.  A request has been looped if the server finds its own address
in the \header{Via} header field \textbf{and} the hash computation over
the fields enumerated in Section~\ref{sec:Via:syntax} yields the same
value as the hash part of the ``\header{branch}'' parameter in the
\header{Via} entry containing the proxy server's address.

A proxy server {\MUSTNOT} forward a request to a multicast group which
already appears in any of the \header{Via} headers.

The proxy server {\MUST} copy all request header fields to the outgoing
request. It {\MAY} add other header fields.

A proxy server always inserts a \header{Via} header field containing its
own address into those requests that are caused by an incoming request. 
Each proxy {\MUST} insert a ``\header{branch}'' parameter
(Section~\ref{sec:Via}). 

Proxies other than outbound proxies {\SHOULD} change the
\header{Request-URI} to indicate the server where it intends to send the
request.

\subsubsection{Proxying Responses}

A proxy only processes a response if the topmost \header{Via} field
matches one of its addresses (see Section \ref{sec:Via}).  A response
with a non-matching top \header{Via} field \header{MUST} be dropped. 
 
\subsubsection{Stateless Proxy: Proxying Responses}
\label{sec:stateless_response}

A stateless proxy {\MUST} follow the procedures in Section~\ref{sec:Via}
in order to determine where to forward the response to. 

A stateless proxy {\MUSTNOT} generate its own provisional
responses. It {\MUST} forward all provisional responses, including
100, upstream.

\subsubsection{Stateful Proxy: Receiving Requests}
\label{sec:stateful_requests}

When a stateful proxy receives a request, it checks the \header{To}
(including tags), \header{From} (including tags), \header{Call-ID},
\header{CSeq}, \header{Request-URI} and topmost \header{Via} against
existing request records. If the tuple exists, the
request is a retransmission.  The provisional or final response sent
previously is retransmitted, as per the server state machine.  If the
tuple does not exist, the request corresponds to a new transaction,
and the request should be proxied.

A stateful proxy server {\MAY} generate its own provisional (1xx)
responses.

\subsubsection{Stateful Proxy: Receiving {\ACK}s}

When an {\ACK} request is received, it is proxied unless the request's
\header{To} (including the tag), \header{From}, \header{CSeq} and
\header{Call-ID} header fields match those of a (non-2xx) response sent
by the proxy.  In that case, the request is processed locally and stops
retransmissions of responses.

\subsubsection{Stateful Proxy: Receiving Responses}

When a proxy server receives a response that has passed the \header{Via}
checks, the proxy server checks the \header{To} (without the tag),
\header{From} (including the tag), \header{Call-ID} and \header{CSeq}
against values seen in previous requests.  If there is no match, the
response is forwarded upstream.  If there is a match, the
``\header{branch}'' tag in the \header{Via} field is examined.  If it
matches a known branch identifier, the response is for the given branch,
and processed by the virtual client for the given branch.  Otherwise,
the response is dropped.

A stateful proxy should obey the rules in
Section~\ref{sec:server-several} to determine if the response should be
proxied upstream.  If it is to be proxied, the same rules for stateless
proxies above are followed, with the following addition for TCP.  If a
request was received via TCP (indicated by the protocol in the top
\header{Via} header), the proxy checks to see if it has a connection
currently open to that address.  If so, the response is sent on that
connection.  Otherwise, a new TCP connection is opened to the address
and port in the \header{Via} field, and the response is sent there. 
Note that this implies that a UAC or proxy {\MUST} be prepared to
receive responses on the incoming side of a TCP connection.  Definitive
non 200-class responses {\MUST} be retransmitted by the proxy, even over
a TCP connection.

\subsubsection{Stateless, Non-Forking Proxy}

Stateless, non-forking proxies issue at most a single unicast request
for each incoming SIP request, that is, they do not ``fork'' requests. 
However, servers {\MAY} choose to always operate in a mode that allows
issuing of several requests, as described in
Section~\ref{sec:server-several}.

The server can forward the request and any responses.  It does not have
to maintain any state for the SIP transaction.  Reliability is assured
by the next redirect or stateful proxy server in the server chain.

A proxy server {\SHOULD} cache the result of any address translations
and the response to speed forwarding of retransmissions.  After the
cache entry has been expired, the server cannot tell whether an incoming
request is actually a retransmission of an older request.  The server
will treat it as a new request and commence another search.

\subsection{Forking Proxy}
\label{sec:server-several}

The server must respond to the request (other than {\ACK}) immediately
with a 100 (Trying) response if it expects to take more than 200\,ms to
obtain a final response.

Successful responses to an {\INVITE} request {\MAY} contain a
\header{Contact} header field so that the following {\ACK} or {\BYE}
bypasses the proxy search mechanism.  If the proxy requires future
requests to be routed through it, it adds a \header{Record-Route} header
to the request (Section \ref{sec:Record-Route}).

The following C-code describes the behavior of a proxy server issuing
several requests in response to an incoming request with method $R$
which is to be proxied to a list of $N$ destination enumerated in
'\emph{address}', with an expiration time of '\emph{expires}' seconds.

The function {\tt request($r$, $a$, $b$)} sends a SIP request of type
$r$ to address $a$, with branch id $b$.  {\tt await\_response()} waits
until a response is received and returns the response.  {\tt close($a$)}
closes the TCP connection to client with address $a$.  {\tt
response($r$)} sends a response to the client.  {\tt ismulticast()}
returns 1 if the location is a multicast address and zero otherwise. 
The variable {\tt timeleft} indicates the amount of time left until the
maximum response time has expired.  The variable {\tt recurse} indicates
whether the server will recursively try addresses returned through a 3xx
response.  A server {\MAY} decide to recursively try only certain
addresses, e.g., those which are within the same domain as the proxy
server.  Thus, an initial multicast request can trigger additional
unicast requests.

\begin{verbatim}
  /* request type */
  typedef enum {INVITE, ACK, BYE, OPTIONS, CANCEL, REGISTER} Method;

  process_request(Method R, int N, address_t address[], int expires)
  {
    struct {
      char *branch;         /* branch token */
      int branch_seq;       /* branch sequence number part */
      int done;             /* has responded */
    } outgoing[];
    char *location[];       /* list of locations */
    int heard = 0;          /* number of sites heard from */
    int class;              /* class of status code */
    int timeleft = expires; /* expiration value */ 
    int loc = 0;            /* number of locations */
    struct {                /* response */
      int status;           /* response: CANCEL=-1 */
      int locations;        /* number of redirect locations */
      char *location[];     /* redirect locations */ 
      address_t a;          /* address of respondent */
      char *branch;         /* branch token */
      int branch_seq;       /* branch sequence number */
    } r, best;              /* response, best response */
    int i;

    best.status = 1000;
    for (i = 0; i < N; i++) {
      request(R, address[i], i);
      outgoing[i].done = 0;
      outgoing[i].branch = "";
      outgoing[i].branch_seq = i;
    }

    while (timeleft > 0 && heard < N) {
      r = await_response();
      class = r.status / 100;

      /* If final response, mark branch as done. */
      if (class >= 2) {
        heard++;
        for (i = 0; i < N; i++) {
          if (r.branch_seq == outgoing[i].branch_seq) {
            outgoing[i].done = 1;
            break;
          }
        }
      }
      /* CANCEL: respond, fork and wait for responses */
      /* terminate INVITE with 407 */
      else if (class < 0) {
        best.status = 200;
        response(best);
        for (i = 0; i < N; i++) {
          if (!outgoing[i].done)
            request(CANCEL, address[i], outgoing[i].branch);
        }
        best.status = -1;
      }

      /* Send an ACK for INVITEs */
      if (class != 2) {
        if (R == INVITE) request(ACK, r.a, r.branch);
      }

      if (class == 2) {
        if (r.status < best.status) best = r;
        break;
      }
      else if (class == 3) {
        /* A server MAY optionally recurse.  The server MUST check
         * whether it has tried this location before and whether the
         * location is part of the Via path of the incoming request. 
         * This check is omitted here for brevity.  Multicast locations
         * MUST NOT be returned to the client if the server is not
         * recursing.
         */
        if (recurse) {
          multicast = 0;
          N += r.locations;
          for (i = 0; i < r.locations; i++) {  
            request(R, r.location[i]);
          }
        } else if (!ismulticast(r.location)) {
          best = r;
        }
      }
      else if (class == 4) {
        if (best.status >= 400) best = r;
      }
      else if (class == 5) {
        if (best.status >= 500) best = r; 
      }
      else if (class == 6) {
        best = r;
        break;
      }
    }

    /* We haven't heard anything useful from anybody. */
    if (best.status == 1000) {
      best.status = 408; /* request expired */
    }
    if (best.status/100 != 3) loc = 0;
    response(best);
  }
\end{verbatim}

Responses are processed as follows.  The process completes (and state
can be freed) when all requests have been answered by final status
responses (for unicast) or 60 seconds have elapsed (for multicast).
A proxy {\SHOULD} send a {\CANCEL} to all incomplete
branches and return the best available final status to the client if
not all responses have been received after 60 seconds or the
expiration period specified in the
\header{Expires} header field of the request. If no
responses have been 
received, the proxy returns a 408 (Timeout) response to the client.

When forwarding responses, a proxy {\MUST} forward the whole response,
including {\em all} header fields of the selected response as well as
the body.

\begin{description}
\item[1xx:] The proxy {\MUST} forward provisional responses greater
than 100 upstream towards the client and {\SHOULDNOT} forward 100
(Trying) responses.

\item[2xx:] If the request was an {\INVITE}, the proxy {\MUST} forward
the response upstream towards the client, without sending an {\ACK}
downstream.  For other requests, it should only forward the response
upstream if it has not forwarded any other responses upstream.

After receiving a 2xx, the server {\SHOULD} terminate all other pending
requests by sending a {\CANCEL} request.  (Terminating pending requests
is advisable as searches consume resources.  Also, {\INVITE} requests
could ``ring'' on a number of workstations if the callee is currently
logged in more than once.)

If the request was not an {\INVITE}, the proxy {\SHOULD} drop 2xx
responses if it had already forwarded a final response upstream.

\item[3xx:] For {\INVITE} requests, the proxy {\MUST} send an {\ACK}. 
It {\MAY} recurse on the listed \header{Contact} addresses.  Otherwise,
the lowest-numbered response is returned if there were no 2xx or 6xx
responses.  \motivation{Location lists are not merged as that would
prevent forwarding of authenticated responses.  Also, responses can have
message bodies, so that merging is not feasible.}

\item[4xx, 5xx:] For {\INVITE} requests, the proxy {\MUST} send an
{\ACK}.  It remembers the response if it has a lower status code class
than any previous 4xx and 5xx response.  On completion, a response with
the lowest response class is returned if there were no 2xx, 3xx or 6xx
responses.  Within the set of responses from the lowest-numbered class,
the proxy server may choose any response.

The proxy {\SHOULD} collect all \header{WWW-Authenticate} and
\header{Proxy-Authenticate} headers from all 401 and 407 responses and
return all of them in the response if either 401 or 407 is the
lowest-numbered response.

\item[6xx:] For {\INVITE} requests, the proxy sends an {\ACK}.  It
forwards the 6xx response unless a 2xx response has been received. 
Other pending requests {\SHOULD} be terminated with {\CANCEL} as described
for 2xx responses. Unlike for 2xx responses, only one 6xx response is
forwarded, since {\ACK}s are generated locally.

\end{description}

A proxy server forwards any response for \header{Call-ID}s for which it
does not have a pending transaction according to the response's
\header{Via} header.  User agent servers respond to {\BYE} requests for
unknown call legs with status code 481 (Transaction Does Not Exist);
they drop {\ACK} requests with unknown call legs silently.

Special considerations apply for choosing forwarding destinations for
{\ACK} and {\BYE} requests.  In most cases, these requests will bypass
proxies and reach the desired party directly, keeping proxies from
having to make forwarding decisions.

A proxy {\MAY} maintain call state for a period of its choosing.  If a
proxy still has list of destinations that it forwarded the last
{\INVITE} to, it {\SHOULD} direct {\ACK} requests only to those
downstream servers. 
