Dale writes:
> > The interesting situation is when the route of a dialog
> > passes through the same proxy more than once. In that case,
> > do all of the "passages"
> > through that proxy share the same state, or does each passage
> > have its own state? I would expect the latter to work more
> > reliably (as the plugins that read and write the route state
> > are likely to be written implicitly assuming that a "passage"
> > through the plugin won't have its state modified by another
> > "passage" through the same plugin).
and Robert replies:
> I disagree but I guess it really depends on the nature of the plug-in.
> In the specific case of NAT traversal, on the second pass, it is
> possible that the location of the called party becomes clearer such that
> it is in a position to provide better NAT compensation of the call. In
> this case, I would want all the RouteStates to contain the 'better'
> information so that it gets used by the plugin regardless of the pass.
>
> Generally speaking, given that plug-ins have been created at the time
> where only one RouteState could ever exist per proxy, the safest thing
> to do to ensure that they continue to work after we allow multiple
> RouteStates/proxy is to make sure that they are identical.
Yes, which makes the current implementation understandable, but if we
can make it work without creating multiple copies of the same data,
that's clearly better because some of these state parameters can be
quite large.
Going back to the purpose of route state: to provide a way to
communicate state established during dialog creation to a proxy plugin
when subsequent messages pass through some proxy. The real semantics of
the particular item of state information have a strong effect on how the
route must be set up in order to work correctly.
My current thinking is that there are two circumstances for any given
item of route state information:
A. Position in the route set matters.
This is clearly the case with the NAT traversal data -
the state that identifies the path to the NATed peer
must be in the route that specifies the particular proxy
that established the NAT mapping and added it to the
route state.
B. Position in the route set does not matter, so long as the state
is somewhere in the set.
This is related to another aspect of the route set that has been a
design goal previously but not exploited: that some state information is
specific to a particular proxy, and other state information could be
applied by any proxy in the same domain.
Until now, we've always inserted proxy Record-Routes using the IP
address of the proxy - never using a DNS SRV name, even though in theory
most of the state we've been inserting has not been tied to a particular
proxy, but could be used by any of the redundant proxies. Put another
way, our Routes have been to the system, not to the domain. This choice
was (like the choice to duplicate state when there are multiple routes
to the same system) a 'safe' one - we knew that any reasonable SIP
implementation would use an IP address (system Route) correctly, but
were less confident that an SRV name (domain Route) would work. This
has had the effect that HA failover works for call setup, but does not
help for established calls: if a call is up and the particular proxy
through which its signaling is Routed fails, no further signaling in
that call (hold, transfer, disconnect) will work (for a non-NATed call,
media will still work - whether or not media continues to work on a
NATed call depends on whether or not the relay process on the proxy is
also affected by the failure). As the number of phones in our
supportable deployments rises, and as the number of systems we want to
support also goes up (multiple survivable branches), it would be good to
begin exploiting redundancy for established calls (it may be that some
implementations won't use it, but that's something that can only be
determined by testing, and which we could eventually hope to have
fixed).
I think that these two issues can be safely conflated - that is:
* Any position-dependent state must be in a system Route
* Any position-independent state may be in a domain Route.
(it's possible that there are examples of position-dependent state that
could be in a domain Route, but I can't think of any case in which
putting it in a system Route would not work. It's easy to think of
examples where the reverse is not true, though, so I think that the rule
above is a good one)
Please review the following modified rules and examples for RouteState
to see if you can find ways that fail to get the behavior we need:
* The RouteState mechanism explicitly distinguishes between routes
that are system-specific and domain-specific. (This would be
coded into the sipXecs-rs value somehow - none of the examples
that follow show this explicitly; in those examples, any route
with an IP address is a system route, any with a name is a
domain route).
* The 'type' of a mutable RouteState can be changed from 'domain'
to 'system', but not from 'system' to 'domain'. (it may be that
we don't need this - see rules for pushing a route below;
opinions on this are solicited)
* When adding a value to a RouteState, always add any new
parameter to the topmost Route regardless of which type it is.
* Add an explicit RouteState operation to push a new Route onto a
mutable RouteState; this operation specifies that the new Route
is either system or domain specific and the hostpart for the new
route. This new Route then becomes the topmost route for the
purposes of adding any new parameter. If the topmost route in
the RouteState and the pushed route are both 'domain' routes,
the push operation just changes the hostpart of that topmost
route to the new value and does not actually add a route (so
'example.com' might be changed to 'boston.example.com' if both
of those are domains rather than systems). If the topmost route
and the pushed route are both 'system' routes, they are combined
only if the hostparts are identical.
* The values available to plugins in a mutable (dialog-forming)
RouteState are all values from all received Record-Route
headers.
* The values available to plugins in a non-mutable (in-dialog)
RouteState are only the values from those Route headers that
were removed.
Given these rules, a plugin that does not care about position or system
binding can just add and modify parameters as in the original RouteState
design. A plugin that needs to ensure that its parameters are bound to
the system and that position is preserved can unconditionally push a
system route into the RouteState and add parameters (multiple plugins
doing this in the same system will end up adding only one system Route).
Examples (items in parens are a 'decoded' version of the parameters
stored in the state, for easier reading):
* If the topmost Route in a request is a domain route:
Record-Route: <sip:example.com;sipXecs-rs=(b=y)>
a plugin may change the RouteState object to be system-specific
and then add parameter 'a=x'. The generated route becomes:
Record-Route: <sip:192.168.10.1;sipXecs-rs=(b=y,a=x)>
* If the topmost Route in a request is a domain route:
Record-Route: <sip:example.com;sipXecs-rs=(b=y)>
a plugin may push a system-specific route and then add parameter
'a=x'. The generated route becomes:
Record-Route: <sip:192.168.10.1;sipXecs-rs=(a=x)>
Record-Route: <sip:example.com;sipXecs-rs=(b=y)>
* If the topmost received Record-Route in a request is a system
route:
Record-Route: <sip:192.168.10.1;sipXecs-rs=(b=y)>
the plugin cannot change that to a domain route (because whoever
inserted 'b=y' explicitly made it system-specific), so inserting
parameter 'a=x', the generated route becomes:
Record-Route: <sip:192.168.10.1;sipXecs-rs=(a=x,b=y)>
I think that this formulation allows both position-dependent
(system-specific) plugins and position-independent (domain-specific)
parameters to be handled correctly, and ensures that they are always
available to the same system that set them, and in the case of
domain-specific parameters to any proxy taking that place the route
set.
_______________________________________________
sipx-dev mailing list [email protected]
List Archive: http://list.sipfoundry.org/archive/sipx-dev
Unsubscribe: http://list.sipfoundry.org/mailman/listinfo/sipx-dev
sipXecs IP PBX -- http://www.sipfoundry.org/