Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
ref_manual:selects [2012/03/15 09:03]
109.230.216.225 FQMiCeqSQnI
ref_manual:selects [2012/05/24 21:17] (current)
oej
Line 1: Line 1:
-Hmm it seems like your site ate my first comment (it was super long) so I guess I'll just sum it up what I wrote and sayI'm rohthugoly enjoying your blogas well am an aspiring blog blogger but I'm still new to everythingDo you have any points for rookie blog writersI'd definitely appreciate it.         +====== The Select Framework ====== 
 +//(written by Michal Matyska)// 
 + 
 +You might ask, why the select framework was introduced at all? The main reason 
 +was that everytime you wanted to check any part (header, etc.of the 
 +incoming message you had to write new module/new function which did that. 
 +Moreover this function (due to historic limitations) might get at most two 
 +parameters. If you need more you have to use workaround and set attributes 
 +which are then checked from this function. So to make the route script more 
 +readable and understandable a new element has started to be supported - the 
 +select framework. 
 + 
 +In the script the select is identified by it's unique name. The intention is 
 +to make the identifier as much understandable as possible, so e.g. if you see 
 +''@to.uri.user'' it is quite obvious, that you'd get the username from the uri 
 +present in the "To" header. Wherever you see the select identifier in the 
 +script, it is actually its value, which is then used during the route script 
 +process. 
 + 
 +To make the select framework speed efficient, the identifier of the select is 
 +parsed and fixed on the SER startup. If it is not valid select identifier, 
 +error message is dumped and SER does not start at all.  But then, during the 
 +request route script execution, there is just single function call invocation, 
 +which gets the parsed select identifier as parameter if it needs it for any 
 +purpose. From the performance point of view there is almost no difference 
 +between calling specialized function from any module and calling function 
 +which represents the select identifier. 
 + 
 +===== Overview of Operation ===== 
 +What we call select is basically unified notation for calling function which 
 +is defined as select function either in SER's core or from any module. The 
 +identifier starts with at sign and consists of few text elements denoted by 
 +dot optionally adding single integer or string parameter enclosed in square 
 +brackets. 
 + 
 +You can use selects in the routing script in the expression evaluationas 
 +right side of attribute assignment and as parameters in some function calls. 
 +(This is limited to functions which support this and the parameter is actually 
 +text with the select identifier, so it must be enclosed in double quotes.) 
 +Xlog formatting also support selects as a element while composing the final 
 +value - the formatting element is ''%@select.identifier.as.usual''
 + 
 +Return value of the select is text string, but be aware, it might be also 
 +string with 0 length (empty string) if such value is allowed (e.g.  some uri 
 +parameter value) or when select function signalizes that expected value was 
 +not found in the header or message parsing encountered syntax error. This kind 
 +of error has influence on the conditional expression - if there is problem 
 +with the select evaluation, the result is false regardless it matches the 
 +empty string. 
 + 
 +===== Select Identifiers ===== 
 +Select identifier starts with at sign (@) followed by at least one (at most 
 +30) text elements each separated by dot (.) from the previous one.  The 
 +identifier elements are case insensitive, so you can e.g. use letter case to 
 +emphasize some of them, but lower case is preferred. Some of the select 
 +functions accept parameters (like index of the repetead headers, or the header 
 +name or authorization realm) - this parameter is expressed in the identifier 
 +by enclosing it with square brackets. The index starts counting from 1 
 +(programmers be aware), because it is more natural and you can also express 
 +that you want count the headers in the opposite direction and get the last 
 +header (using -1 as the index). 
 + 
 +Examples of identifiers (syntactically valid): 
 +  * ''@the.simplest'' 
 +  * ''@another.with!["parameter"]'' 
 +  * ''@yet.another![1].parameter![2]'' 
 +  * ''@you.can.also.mix.string!["like-this"].and.integer![1].parameters'' 
 + 
 +===== Nested Selects ===== 
 +You might find some repeating patterns in the SIP requests, like that there is 
 +URI element present in quite a lot of SIP headers. The select framework has 
 +possibility to ease the developers' life reusing the URI parser and select 
 +function already included in the core (or parser of parameter values (either 
 +header or URI), or any other if you are able to think it off) and apply it on 
 +intermediate select result This so called nested select (see developers' doc 
 +if you are interested) divides the select call to two (or more) separate 
 +function calls, where the first one returns the URI text as temporary result, 
 +which is then passed to the built-in URI select machinery as the value which 
 +should be used for the final result.  E.g. 
 +''@hf_value!["X-any-header"].nameaddr.uri.user'' gets the value of X-any-header 
 +header, assuming it is conforming to the name-addr RFC specification and 
 +passes the header value to the name-addr select-parser, which separates the 
 +username from the URI and returns that as the final value of the select. 
 + 
 +So every of these URIs (select's results) can be passed to URI specialized 
 +select, which makes individual URI parts accessible. 
 + 
 +  @request_uri, @dst_uri, @next_hop, @from.uri, @to.uri, @refer_to.uri, 
 +  @rpid.uri, @contact.uri, @record_route.uri or 
 +  @hf_value!["any-header"].nameaddr.uri - all these return appropriate URI. 
 + 
 +Now if you want just the username, append .user to the select identifier and 
 +you get the username. The .user identifier part is everytime same regardless 
 +which URI was selected in the first step. 
 + 
 +Here is the list of all URI's nested select identifiers: 
 +   * ''type'': returns the URI type in normalized (lowercase) text sip, sips, tel, tels 
 +   * ''user'' 
 +   * ''pwd'' 
 +   * ''host'' 
 +   * ''port'': all above is selfexplaining 
 + 
 +   * ''transport'': returns the transport parameter value if present, otherwise the default transport used based on the URI type. 
 +   * ''hostport'': returns the host:port value from the URI. If the port is not present, the default value based on the URI type is used. 
 +   * ''params'': the whole parameters part of URI like user=phone;phone-context=+1234 
 +   * ''params!["parameter-name"]'': just the value of the specified parameter 
 + 
 +===== Selects in Expressions ===== 
 +You can use the select in the conditional expressions like these: 
 + 
 +  if (@select.value) {...} 
 + 
 +the test is true, when the select returns NON-EMPTY string. 
 + 
 +<note> 
 +This way of using select is obsolete and it will generate a warning message on start-up. 
 +For sip-router the if will be true only if it returns a non-empty, non-zero numerical string (e.g. "123"). 
 +The preferred correct ways for sip-router are: 
 + 
 +  if (@select.value!=""
 + 
 +or 
 + 
 +  if (!strempty(@select.value)) 
 + 
 +</note> 
 + 
 + 
 +  if (@select.value=="string") {...} 
 +  if ("string"==@select.value) {...} 
 + 
 +the result is true, when the select is error-free and its return value is equal to "string"
 +Instead of a constant value, you can use any expression (it could involve avps, pvars or other selects). 
 + 
 +  if (@select.value!="string") {...} 
 +  if ("string"!=@select.value) {...} 
 + 
 +in this case the test checks whether the two strings are different. If 
 +there is error during the select evaluation, the result is also false. 
 + 
 +  if (@select.value=~"reg.*expr.?") {...} 
 + 
 +true, when the string returned by select function matches the regular 
 +expression. In this case swapping of the left and right values matter, so 
 + 
 +  if ("string"=~@select.value) {...} 
 + 
 +is true when the "string" matches the regular expression, which is 
 +obtained as select's return value. This is what you usually don't want. 
 + 
 +You can also use the select in any kind of expression, be it in the right hand of an assignment, in an if, while() or switch(). 
 + 
 +E.g.: 
 +  $attribute=@the.select.you.want 
 + 
 +===== Selects in Parameters ===== 
 +Some functions allow to pass the select's return value as parameter. The 
 +function must support that, so it is not possible for every function. The 
 +parameter holds the select identifier and the function is responsible to 
 +resolve and fixup the indetifier at SER startup and then call the select 
 +function to obtain the return value. 
 + 
 +If the select's evaluation has stopped with error, then the return value of 
 +the function is false and the rest of the function's code is typically skipped 
 +over. 
 + 
 +===== System Selects ===== 
 +As the select framework has begun to show its strength, new ideas whatever 
 +else could be accessible using select call has emerged. The example of that 
 +are system selects which's identifiers begin with @sys like: 
 + 
 + * ''@sys.pid'': returns string representation of current process # 
 + * ''@sys.now'': unix timestamp or 
 + * ''@sys.utc'': UTC timestamp if you use different time zones 
 + * ''@sys.unique'': generates and returns random UUID (type 2) 
 + 
 +===== Selects in Modules ===== 
 +As you can see, the select framework is very powerfull tool, which can be 
 +easily extended using the SER's modules concept. E.g. the TLS module, there is 
 +lot of TLS information you can get/check in the script, but only when the TLS 
 +module is used. So all the TLS related selects are part of the TLS module... 
 +if you use the module, then they are available, if you don't use the module, 
 +they are not and SER will complain about the wrong select identifier and 
 +decline to start. 
 + 
 +On the other hand, there is no difference between the module's selects and 
 +core's selects, so you don't really need to care where is the source of the 
 +select, just make sure you have loaded all neccessary modules. 
 + 
 + 
 +===== Select List ===== 
 + 
 +For a list with all the defined selects in the sip-router devel version (master branch), see 
 +[[http://sip-router.org/docbook/sip-router/branch/master/select_list/select_list.html]].

Navigation

Wiki

Other

QR Code
QR Code ref_manual:selects (generated for current page)