with a header field value in the Accept-Contact header field, the
feature set predicate derived from that header field value is said to
have its require flag set. Similarly, if there was an explicit-param
associated with a header field value in the Accept-Contact header
field, the feature set predicate derived from that header field value
is said to have its explicit flag set.
7.2.2. Extracting Implicit Preferences
If, and only if, the proxy did not find any explicit preferences in
the request (because there was no Accept-Contact or Reject-Contact
header field), the proxy extracts implicit preferences. These
preferences are ones implied by the presence of other information in
the request.
First, the proxy creates a conjunction with no terms. This
conjunction represents a feature set that will be associated with the
Accept-Contact header field, as if it were included there. Note that
there is no modification of the message implied - only an association
for the purposes of processing. Furthermore, this feature set has
its require flag set, but not its explicit flag.
The proxy then adds terms to the conjunction for the two implicit
preference types below.
7.2.2.1. Methods
One implicit preference is the method. When a UAC sends a request
with a specific method, it is an implicit preference to have the
request routed only to UAs that support that method. To support this
implicit preference, the proxy adds a term to the conjunction of the
following form:
(sip.methods=[method of request])
7.2.2.2. Event Packages
For requests that establish a subscription [5], the Event header
field is another expression of an implicit preference. It expresses
a desire for the request to be routed only to a server that supports
the given event package. To support this implicit preference, the
proxy adds a term to the conjunction of the following form:
(sip.events=[value of the Event header field])
7.2.3. Constructing Contact Predicates
The proxy then takes each URI in the target set (the set of URI it is
going to proxy or redirect to), and obtains its capabilities as an
RFC 2533 formatted feature set predicate. This is called a contact
predicate. If the target URI was obtained through a registration,
the proxy computes the contact predicate by extracting the feature
parameters from the Contact header field [3] and then converting them
to a feature predicate. To extract the feature parameters, the proxy
follows these steps:
1. Create an initial, empty list of feature parameters.
2. If the Contact URI parameters included the "audio", "automata",
"class", "duplex", "data", "control", "mobility", "description",
"events", "priority", "methods", "schemes", "application",
"video", "actor", "language", "isfocus", "type", "extensions", or
"text" parameters, those are copied into the list.
3. If any Contact URI parameter name begins with a "+", it is copied
into the list if the list does not already contain that name with
the plus removed. In other words, if the "video" feature
parameter is in the list, the "+video" parameter would not be
placed into the list. This conflict should never arise if the
client were compliant to [3], since it is illegal to use the +
form for encoding of a feature tag in the base set.
If the URI in the target set had no feature parameters, it is said to
be immune to caller preference processing. This means that the URI
is removed from the target set temporarily, the caller preferences
processing described below is executed, and then the URI is added
back in.
Assuming the URI has feature parameters, they are converted to RFC
2533 syntax using the rules of Section 8.
The resulting predicate is associated with a q-value. If the contact
predicate was learned through a REGISTER request, the q-value is
equal to the q-value in the Contact header field parameter, else
"1.0" if not specified.
As an example, consider the following registered Contact header
field:
Contact: <sip:user@example.com>;audio;video;mobility="fixed";
+sip.message="TRUE";other-param=66372;
methods="INVITE,OPTIONS,BYE,CANCEL,ACK";schemes="sip,http"
This would be converted into the following predicate:
(& (sip.audio=TRUE)
(sip.video=TRUE)
(sip.mobility=fixed)
(sip.message=TRUE)
(| (sip.methods=INVITE) (sip.methods=OPTIONS) (sip.methods=BYE)
(sip.methods=CANCEL) (sip.methods=ACK))
(| (sip.schemes=sip) (sip.schemes=http)))
Note that "other-param" was not considered a feature parameter, since
it is neither a base tag nor did it begin with a leading +.
7.2.4. Matching
It is important to note that the proxy does not have to know anything
about the meaning of the feature tags that it is comparing in order
to perform the matching operation. The rules for performing the
comparison depend on syntactic hints present in the values of each
feature tag. For example, a predicate such as:
(foo>=4)
implies that the feature tag "foo" is a numeric value. The matching
rules in RFC 2533 only require an implementation to know whether the
feature tag is a numeric, token, or quoted string (booleans can be
treated as tokens). Quoted strings are always matched using a case-
sensitive matching operation. Tokens are matched using case-
insensitive matching. These two cases are differentiated by the
presence of angle brackets around the feature tag value. When these
brackets are present (i.e., ;+sip.foo="<value>"), it implies case
sensitive string comparison. When they are not present, (i.e.,
(;+sip.bar="val"), it implies case insensitivity. Numerics are
matched using normal mathematical comparisons.
First, the proxy applies the predicates associated with the Reject-
Contact header field.
For each contact predicate, each Reject-Contact predicate (that is,
each predicate associated with the Reject-Contact header field) is
examined. If that Reject-Contact predicate contains a filter for a
feature tag, and that feature tag is not present anywhere in the
contact predicate, that Reject-Contact predicate is discarded for the
processing of that contact predicate. If the Reject-Contact
predicate is not discarded, it is matched with the contact predicate
using the matching operation of RFC 2533 [2]. If the result is a
match, the URI corresponding to that contact predicate is discarded
from the target set.
The result is that Reject-Contact will only discard URIs where the UA
has explicitly indicated support for the features that are not
wanted.
Next, the proxy applies the predicates associated with the Accept-
Contact header field. For each contact that remains in the target
set, the proxy constructs a matching set, Ms. Initially, this set
contains all of the Accept-Contact predicates. Each of those
predicates is examined. It is matched with the contact predicate
using the matching operation of RFC 2533 [2]. If the result is not a
match, and the Accept-Contact predicate had its require flag set, the
URI corresponding to that contact predicate is discarded from the
target set. If the result is not a match, but the Accept-Contact
predicate did not have its require flag set, that contact URI is not
discarded from the target set, however, the Accept-Contact predicate
is removed from the matching set for that contact.
For each contact that remains in the target set, the proxy computes a
score for that contact against each predicate in the contact’s
matching set. Let the number of terms in the Accept-Contact
predicate conjunction be equal to N. Each term in that predicate
contains a single feature tag. If the contact predicate has a term
containing that same feature tag, the score is incremented by 1/N.
If the feature tag was not present in the contact predicate, the
score remains unchanged. Based on these rules, the score can range
between zero and one.
T
+----------> DROP Contact
|
|
/ \
/ \
T / \ F
+---->/require\------> Set score=0
| \ /
| \ /
/ \ \ /
/ \ \/
score<1 / \
+-------> /explicit----> Score unchanged
| \ / F
| \ /
/ \ \ /
/ \ \/
+--------+ / \
-->|Compute |--> /Score \ --------> Score unchanged
| Score | \ / score=1
+--------+ \ /
\ /
\/
Figure 1: Applying the Score
The require and explicit tags are then applied, resulting in
potential modification of the score and the target set. This process
is summarized in Figure 1. If the score for the contact predicate
against that Accept-Contact predicate was less than one, the Accept-
Contact predicate had an explicit tag, and if the predicate also had
a require tag, the Contact URI corresponding to that contact
predicate is dropped. If, however, the predicate did not have a
require tag, the score is set to zero. If there was no explicit tag,
the score is unchanged.
The next step is to combine the scores and the q-values associated
with the predicates in the matching set, to arrive at an overall
caller preference, Qa. For those URIs in the target set which
remain, there will be a score which indicates its match against each
Accept-Contact predicate in the matching set. If there are M
Accept-Contact predicates in the matching set, there will be M scores
S1 through SM, for each contact. The overall caller preference, Qa,
is the arithmetic average of S1 through SM.
At this point, any URIs that were removed from the target set because
they were immune from caller preferences are added back in, and Qa
for that URI is set to 1.0.
The purpose of the caller preference Qa is to provide an ordering for
any contacts remaining in the target set, if the callee has not
provided an ordering. To do this, the contacts remaining in the
target set are sorted by the q-value provided by the callee. Once
sorted, they are grouped into equivalence classes, such that all
contacts with the same q-value are in the same equivalence class.
Within each equivalence class, the contacts are then ordered based on
their values of Qa. The result is an ordered list of contacts that
is used by the proxy.
If there were no URIs in the target set after the application of the
processing in this section, and the caller preferences were based on
implicit preferences (Section 7.2.2), the processing in this section
is discarded, and the original target set, ordered by their original
q-values, is used.
This handles the case where implicit preferences for the method or
event packages resulted in the elimination of all potential
targets. By going back to the original target set, those URIs
will be tried, and result in the generation of a 405 or 489
response. The UAC can then use this information to try again, or
report the error to the user. Without reverting to the original
target set, the UAC would see a 480 response, and have no
knowledge of why their request failed. Of course, the target set
can also be empty after the application of explicit preferences.
This will result in the generation of a 480 by the proxy. This
behavior is acceptable, and indeed, desirable in the case of
explicit preferences. When the caller makes an explicit
preference, it is agreeing that its request might fail because of
a preference mismatch. One might try to return an error
indicating the capabilities of the callee, so that the caller
could perhaps try again. However, doing so results in the leaking
of potentially sensitive information to the caller without
authorization from the callee, and therefore this specification
does not provide a means for it.
If a proxy server is recursing, it adds the Contact header fields
returned in the redirect responses to the target set, and re-applies
the caller preferences algorithm.
If the server is redirecting, it returns all entries in the target
set. It assigns q-values to those entries so that the ordering is
identical to the ordering determined by the processing above.
However, it MUST NOT include the feature parameters for the entries
in the target set. If it did, the upstream proxy server would apply
the same caller preferences once more, resulting in a double
application of those preferences. If the redirect server does wish
to include the feature parameters in the Contact header field, it
MUST redirect using the original target set and original q-values,
before the application of caller preferences.
7.2.5. Example
Consider the following example, which is contrived but illustrative
of the various components of the matching process. There are five
registered Contacts for sip:user@example.com. They are:
Contact: sip:u1@h.example.com;audio;video;methods="INVITE,BYE";q=0.2
Contact: sip:u2@h.example.com;audio="FALSE";
methods="INVITE";actor="msg-taker";q=0.2
Contact: sip:u3@h.example.com;audio;actor="msg-taker";
methods="INVITE";video;q=0.3
Contact: sip:u4@h.example.com;audio;methods="INVITE,OPTIONS";q=0.2
Contact: sip:u5@h.example.com;q=0.5
An INVITE sent to sip:user@example.com contained the following caller
preferences header fields:
Reject-Contact: *;actor="msg-taker";video
Accept-Contact: *;audio;require
Accept-Contact: *;video;explicit
Accept-Contact: *;methods="BYE";class="business";q=1.0
There are no implicit preferences in this example, because explicit
preferences are provided.
The proxy first removes u5 from the target set, since it is immune
from caller preferences processing.
Next, the proxy processes the Reject-Contact header field. It is a
match for all four remaining contacts, but only an explicit match for
u3. That is because u3 is the only one that explicitly indicated
support for video, and explicitly indicated it is a message taker.
So, u3 gets discarded, and the others remain.
Next, each of the remaining three contacts is compared against each
of the three Accept-Contact predicates. u1 is a match to all three,
earning a score of 1.0 for the first two predicates, and 0.5 for the
third (the methods feature tag was present in the contact predicate,
but the class tag was not). u2 doesn’t match the first predicate.
Because that predicate has a require tag, u2 is discarded. u4
matches the first predicate, earning a score of 1.0. u4 matches the
second predicate, but since the match is not explicit (the score is
0.0, in fact), the score is set to zero (it was already zero, so
nothing changes). u4 does not match the third predicate.
At this point, u1 and u4 remain. u1 matched all three Accept-Contact
predicates, so its matching set contains all three, with scores of 1,
1, and 0.5. u4 matches the first two predicates, with scores of 1.0
and 0.0. Qa for u1 is 0.83 and Qa for u4 is 0.5. u5 is added back
in with a Qa of 1.0.
Next, the remaining contacts in the target set are sorted by q-value.
u5 has a value of 0.5, u1 has a q-value of 0.2 and so does u4. There
are two equivalence classes. The first has a q-value of 0.5, and
consists of just u5. Since there is only one member of the class,
sorting within the class has no impact. The second equivalence class
has a q-value of 0.2. Within that class, the two contacts, u1 and
u4, are ordered based on their values of Qa. u1 has a Qa of 0.83,
and u4, a Qa of 0.5. Thus, u1 comes first, followed by u4. The
resulting overall ordered set of contacts in the target set is u5,
u1, and then u4.
8. Mapping Feature Parameters to a Predicate
Mapping between feature parameters and a feature set predicate,
formatted according to the syntax of RFC 2533 [2], is trivial. It is
just the opposite of the process described in Section 5 of [3].
Starting from a set of feature-param, the procedure is as follows.
Construct a conjunction. Each term in the conjunction derives from
one feature-param. If the feature-param has no value, it is
equivalent, in terms of the processing which follows, as if it had a
value of "TRUE".
If the feature-param value is a tag-value-list, the element of the
conjunction is a disjunction. There is one term in the disjunction
for each tag-value in the tag-value-list.
Consider now the construction of a filter from a tag-value. If the
tag-value starts with an exclamation mark (!), the filter is of the
form:
(! <filter from remainder>)
where "<filter from remainder>" refers to the filter that would be
constructed from the tag-value if the exclamation mark had not been
present.
If the tag-value starts with an octothorpe (#), the filter is a
numeric comparison. The comparator is either =, >=, <=, or a range
based on the next characters in the phrase. If the next characters
are =, >=, or <=, the filter is of the form:
(name comparator compare-value)
where name is the name of the feature parameter after it has been
decoded (see below), and the comparator is either =, >=, or <=
depending of the initial characters in the phrase. If the remainder
of the text in the tag-value after the equal contains a decimal point
(implying a rational number), the decimal point is shifted right N
times until it is an integer, I. Compare-value above is then set to
"I / 10**N", where 10**N is the result of computing the number 10 to
the Nth power.
If the value after the octothorpe is a number, the filter is a range.
The format of the filter is:
(name=<remainder>)
where "name" is the feature-tag after it has been decoded (see
below), and "<remainder>" is the remainder of the text in the tag-
value after the #, with any decimal numbers converted to a rational
form, and the colon replaced by a double dot (..).
If the tag-value does not begin with an octothorpe (it is a token-
nobang or boolean), the filter is of the form:
(name=tag-value)
where name is the feature-tag after it has been decoded (see below).
If the feature-param contains a string-value (based on the fact that
it begins with a left angle bracket ("<") and ends with a right angle
bracket (">")), the filter is of the form:
(name="qdtext")
Note the explicit usage of quotes around the qdtext, which indicate
that the value is a string. In RFC 2533, strings are compared using
case sensitive rules, and tokens are compared using case insensitive
rules.
Feature tags, as specified in RFC 2506 [13], cannot be directly
represented as header field parameters in the Contact, Accept-
Contact, and Reject-Contact header fields. This is due to an
inconsistency in the grammars, and in the need to differentiate
feature parameters from parameters used by other extensions. As
such, feature tag values are encoded from RFC 2506 format to yield an
enc-feature-tag, and then are decoded into RFC 2506 format. The
decoding process is simple. If there is a leading plus (+) sign, it
is removed. Any exclamation point (!) is converted to a colon (:)
and any single quote (’) is converted to a forward slash (/). If
there was no leading plus sign, and the remainder of the encoded name
was "audio", "automata", "class", "duplex", "data", "control",
"mobility", "description", "events", "priority", "methods",
"schemes", "application", "video", "actor", "isfocus", "extensions"
or "text", the prefix "sip." is added to the remainder of the encoded
name to compute the feature tag name.
As an example, the Accept-Contact header field:
Accept-Contact:*;mobility="fixed"
;events="!presence,message-summary"
;language="en,de";description="<PC>";+sip.newparam
;+rangeparam="#-4:+5.125"
would be converted to the following feature predicate:
(& (sip.mobility=fixed)
(| (! (sip.events=presence)) (sip.events=message-summary))
(| (language=en) (language=de))
(sip.description="PC")
(sip.newparam=TRUE)
(rangeparam=-4..5125/1000))
9. Header Field Definitions
This specification defines three new header fields - Accept-Contact,
Reject-Contact, and Request-Disposition.
Figure 2 and Figure 3 are an extension of Tables 2 and 3 in RFC 3261
[1] for the Accept-Contact, Reject-Contact, and Request-Disposition
header fields. The column "INF" is for the INFO method [6], "PRA" is
for the PRACK method [7], "UPD" is for the UPDATE method [8], "SUB"
is for the SUBSCRIBE method [5], "NOT" is for the NOTIFY method [5],
"MSG" is for the MESSAGE method [9], and "REF" is for the REFER
method [10].
Header field where proxy ACK BYE CAN INV OPT REG
Accept-Contact R ar o o o o o -
Reject-Contact R ar o o o o o -
Request-Disposition R ar o o o o o o
Figure 2: Accept-Contact, Reject-Contact, and Request-Disposition
header fields
Header field where proxy PRA UPD SUB NOT INF MSG REF
Accept-Contact R ar o o o o o o o
Reject-Contact R ar o o o o o o o
Request-Disposition R ar o o o o o o o
Figure 3: Accept-Contact, Reject-Contact, and Request-Disposition
header fields
9.1. Request Disposition
The Request-Disposition header field specifies caller preferences for
how a server should process a request. Its value is a list of
tokens, each of which specifies a particular directive. Its syntax