Hello,
I thought I would try and produce a short summary (basically just bullet
points) of what is required for Outbound just to make sure I haven't
missed anything.
There are three use cases for Kamailio with Outbound/Path:
* EDGE server between client and registrar
* Registrar with EDGE server between it and client
* Single server (EDGE server and registrar combined) using Outbound
instead of aliasing for NAT traversal
EDGE server
-----------
* Path
- Existing Path module does (most of) what is required when called for
REGISTER requests
- Received parameters are not needed on Path: headers because we will
use Outbound flow tokens now
* Outbound
- Need to generate/add flow token and ;ob parameter to the
Path/Record-Route headers when:
# It's an initial request (out-of-dialog INVITE, REGISTER, SUBSCRIBE,
or REFER), with
# A single Via:, and
# Top Route: points to us and has ;ob parameter or Contact: has ;ob
parameter or it's a REGISTER with ;+sip.instance, or
# force_outbound() API has been called
- Need to maintain mapping of flow tokens to connections (flow token
to/from source address and port)
- Need an Outbound routing API (related to loose_route()) that sets $du
correctly based on flow token in Route: header (R-URI no longer used)
- If the flow token doesn't match a connection send 430 response
(response sending in kamailio.cfg, but Outbound routing API needs to
return an appropriate error to support this)
Registrar
---------
* Path
- Path already supported in usrloc
* Outbound
- instance and reg IDs already stored in usrloc
- multiple registrations with the same instance ID but different reg IDs
must be supported (may be already)
- Parallel and serial forking behaviour must be preserved, when forking
branch to each unique instance ID not reg ID.
- Need a new/improved lookup() API that returns the location for the
best reg ID and populates an AVP with the other instance IDs in order
they should be tried
- On receipt of 430 response to a request the failed location should be
removed from the usrloc table and the next location (from the AVP)
tried. Similar to the way dispatcher works.
Single server
-------------
* Path
- Use this to add single (local) Path header - just needed to get the
Outbound flow token into the usrloc table
- Received parameters are not needed on Path: headers because we will
use Outbound flow tokens now
* Outbound
- Similar to the combined behaviour of EDGE server and Registrar, but
because the mapping of flow token to connection is local there is no
need for the 430 response stuff - can just loop through the list of
matching connections locally until a good one is found.
Note: Double-Path and advertised address...
* Talking to one of my colleagues he thought that double-Path headers
wouldn't be required. Double-RR is used to make sure the route-set is
good in both directions when there are transport/network changes. Because
Path is just used in the one direction this shouldn't be required. Does
this make sense?
* Because the Path header needs to show the address of the outbound
interface it should use the advertised address for that interface, not the
listening address of the interface. Is this correct?
Proposed API
------------
Right thing to do might be a new outbound module which provides both the
EDGE server and registrar functions. The module would bind (through C-API
- which might need extended/tweaked for each of the modules) to path, rr,
registrar, and location modules to make use of the functions already
implemented there. Probably (when Outbound is used) path, rr, and
registrar will not be called from kamailio.cfg directly - the outbound
wrapper functions will be used instead:
* outbound_route(): use instead of rr.loose_route() (may well call
rr.loose_route() internally but will also use flow token to work out value
for $du)
* outbound_record_route(): use instead of rr.record_route() (may well call
rr.record_route() internally - but will also add the flow token (if the
requirements for Outbound are met in the request))
* outbound_add_path(): use instead of path.add_path() (may well call
path.add_path() internally - but will also add the flow token and generate
it (and add to token/connection mapping table) for new connections (if the
requirements for Outbound are met in the request))
* outbound_lookup(): use instead of registrar.lookup() (may well call
registrar.lookup() internally - but will select the contact(s) with the
best reg IDs and fill in AVP)
* outbound_next_contact(): new API which will remove the first contact
from the AVP _and_ location table and select the best remaining reg ID
* force_outbound(): new API which will make sure flow tokens are added by
outbound_record_route() and outbound_add_path() even if the request
doesn't indicate client support
Token/connection map maintenance
----------------------------------
* Is there a need to add an event_route[] to catch connection closes (and
a corresponding outbound module API to remove a token/connection mapping)
as previously suggested by OEJ?
* Is it OK for the outbound.outbound_route() function just to check that a
connection found in the mapping table is valid when attempting to route a
request (and removing the mapping and returning that there was no mapping
when it isn't) - or would this lead to stuck entries in the mapping table?
* Perhaps entries in the map should expire automatically anyway (so no
catching of closes required) - they will be created when a client
registers so there is an expiry time available?
Thanks,
Peter
--
Peter Dunkley
Technical Director
Crocodile RCS Ltd