Attribute-value pairs and selects

Keywords: 2.0.x | Book | core

There is one major difference between select (@) and AVP($). The select is READ-ONLY "function", the AVP could be used as variable ('coz is read/write).

The select helps to get direct access to some parts of request within the script (like @to, @cseg.method, @msg.["P-anyheader-youwant"]), but generally could be seen as function returning a string with certainnumber of parameters.

Each module can extend the syntax the select framework understands registering it's own select table. Look on TLS module or db_ops as good samples.

The AVPs are sorted into classes and tracks:
GENERAL class (same for both FROM and TO track)
DOMAIN class
USER class
with one interesting feature, that the AVP accesse by the track prefix only is searched in the USER class, if not found in DOMAIN class and then in GLOBAL class, so you can define GLOBAL value, which is overrided by DOMAIN (if desired) and by USER AVPs.

Small example could make it more understandable:
# idea in script syntax
lookup_domain("$td","@ruri"); #load domain attrs with to track based on R-URIi
lookup_user("$tu","@ruri");   #load user attrs with to track based on R-URI
if (!registerd("$t.uid") && ($t.voicemail)) {t_forward_to("","$voicemail"; drop;}

You can set (admin in domain_attrs and user_attrs) when forwarding to the voicemail is desired or not.

if (... ($t.voicemail)) checks if the AVP exists (in user, domain or global class) and if yes, it's value is used as destination for
forwarded request.

The user and domain classes are hold together with other data in tm module, so they are set the same way it were within the on_failure,
on_reply route blocks. All changes done in onbranch route are disposed.

  SERi core can parse select identifiers using the configuration parser.  A select identifiers begins with @ characters and contains several components/tokens delimited by . (unless it is integer component). Integer components are enclosed in [], for example:

  @contact[1].uri

  This identifier is converted into binary structure which contains the array of components. After that the parser tries to lookup function that matches the identifier.

  Available functions are arranged in a tree-like structure. When looking up a function the tree is traversed (starting at the root) until the parser finds corresponding function. For example, the part of the tree containing TLS functions looks like:

  "tls"-+-"peer"-+-"subj"-+-"name" (select_peer_name())
                 |         \
          |          "state" (select_peer_state())
   |
   +-"issuer"-+-"name" (select_peer_issuer_name())
               \
         "state" (select_peer_issuer_state())

  Thus when you write @tls.peer.subj.state in the configuration file then the parser will traverse the tree until it reaches select_peer_state() function and then it would remember that this
  function should be called.

  The tree of identifiers and functions is built dynamically at runtime.  This is a nice feature becase this way modules can register their own
  functions or whole subtrees and make their functions available in the configuration file.

  Thus if you load TLS module then all @tls.* selects become avaiable, if you do not load the module they are not available. Only a couple of
  core functions and the framework is built in the core, the rest can be in modules.

  This framework is currently used in tls and xmlrpc modules. XMLRPC module exports the name of the XML-RPC method to the script. TLS
  module exports information from TLS layer.  The SER core itself contains a couple of functions that can retrieve
  various parts of a SIP message:

@from, @from.uri, @to, @to.uri, @from.tagi, @from.name

@to.tag,  @to.name, @from.params, @to.params,

@contact, @contact.uri,  @contact.params, @contact.expires, @contact.q, @via, and so on.

Home |  Recent changes |  Search |  Glossary |  Sitemap |  Login