Inside the SIPWitch server we use shared conditional locks. Some key
assumptions are made and must never be violated:
Methods that assert modify locks must never aquire additional shared locks;
all their arguments have all data needed to complete the operation
Methods that assert modify locks always either commit or share before they
return. No function will return with a modify lock still held.
Lookup methods will return with a shared lock held if they are successful.
A matching release function will be used to clear the lock when the
object is no longer needed.
Multiple access locks can be held against config by a single thread. This
is valid because only the reload function modifies config or holds a
Only a single access reference should be held for registry or session. The
registry and call sessions may be modified, or locks converted, and this
is only possible if there is no recursive locks. It is possible to
hold recursive locks briefly, but there is a deadlock schedule scenario
possible since further (recursive) reads can be scheduled after writes,
so both registry and session locks should not be held by a thread if either
one is potentially being held recursive.
Never hold a session access lock when acquiring a modify lock to the registry.
There a deadlock scenario possible if registry modify locking or lock
conversion occurs when sessions are accessed. Performing a modify
session lock while holding an active registry access lock is safe, and in
some cases nessisary, which is why deadlocks can occur when someone tryies
to do the reverse.
Non-deterministic blocking operations must never be performed while holding
a modify lock. To avoid writer starvation, they probably should be
avoided while holding an access lock as well outside of config.
About media proxy:
It is assumed that we can reflect (transparently) rtp media for sessions that
do not appear from the same network. This may be either because the user
agents are on different subnets, or one or more ua's are on an "external"
(public) entity outside of the local routing entirely, which is
characteristic of the server being behind a NAT.
The server caches the network policy the user agent appears from at user agent
registration, uses the source network policy at invite from the source/acl
policy detection. This avoids lots of expensive and complex nat detection
and redundant operations. This always assumes the sdp will refer to
media endpoints that always fall under the same network as the user agent
appears to be from in SIP.