User Tools

Site Tools


cookbooks:5.2.x:core

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
cookbooks:5.2.x:core [2019/10/30 00:16]
joelsdc
cookbooks:5.2.x:core [2019/10/30 09:54] (current)
Line 2880: Line 2880:
  
 Add "​user=phone"​ parameter to R-URI. Add "​user=phone"​ parameter to R-URI.
 +
 ===== Custom Global Parameters ===== ===== Custom Global Parameters =====
  
Line 3013: Line 3014:
  
 The sub-route blocks allow to make the configuration file modular, simplifying the logic and helping to avoid duplication of actions. The sub-route blocks allow to make the configuration file modular, simplifying the logic and helping to avoid duplication of actions.
 +==== branch_route ====
 +
 +Request'​s branch routing block. It contains a set of actions to be taken for each branch of a SIP request. It is executed only by TM module after it was armed via t_on_branch("​branch_route_index"​).
 +
 +Example of usage:
 +
 +<code c>
 +    request_route {
 +        lookup("​location"​);​
 +        t_on_branch("​OUT"​);​
 +        if(!t_relay()) {
 +            sl_send_reply("​500",​ "​relaying failed"​);​
 +        }
 +    }
 +    branch_route[OUT] {
 +        if(uri=~"​10\.10\.10\.10"​) {
 +            # discard branches that go to 10.10.10.10
 +            drop();
 +        }
 +    }
 +</​code>​
 +
 +==== failure_route ====
 +
 +Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches. The '​failure_route'​ is executed only by TM module after it was armed via t_on_failure("​failure_route_index"​).
 +
 +Note that in '​failure_route'​ is processed the request that initiated the transaction,​ not the reply .
 +
 +
 +Example of usage:
 +
 +<code c>
 +    request_route {
 +        lookup("​location"​);​
 +        t_on_failure("​TOVOICEMAIL"​);​
 +        if(!t_relay()) {
 +            sl_send_reply("​500",​ "​relaying failed"​);​
 +        }
 +    }
 +    failure_route[TOVOICEMAIL] {
 +        if(is_method("​INVITE"​)) {
 +             # call failed - relay to voice mail
 +             ​t_relay_to_udp("​voicemail.server.com","​5060"​);​
 +        }
 +    }
 +</​code>​
 +
 +==== reply_route ====
 +
 +Main SIP response (reply) handling block - it contains a set of actions to be executed for SIP replies. It is executed for all replies received from the network.
 +
 +It does not have a name and it is executed by the core, before any other module handling the SIP reply. It is triggered only by SIP replies received on the network.
 +
 +There is no network route that can be enforced for a SIP reply - it is sent based on Via header, according to SIP RFC3261 - therefore no dedicated actions for forwarding the reply must be used in this block.
 +
 +This routing block is optional, if missing, the SIP reply is sent to the address in 2nd Via header.
 +
 +One can decide to drop a SIP reply by using **drop** action.
 +
 +Example:
 +
 +<code c>
 +reply_route {
 +  if(status=="​128""​) {
 +    drop;
 +  }
 +}
 +</​code>​
 +
 +<fc #​4682b4>​Note:​ for backward compatibility reasons, the main '​reply'​ routing block can be also identified by '​onreply_route {...}' or '​onreply_route[0] {...}'​.</​fc>​
 +
 +==== onreply_route ====
 +
 +
 +SIP reply routing block executed by **tm** module. It contains a set of actions to be taken for SIP replies in the contect of an active transaction.
 +
 +The '​onreply_route'​ must be armed for the SIP requests whose replies should be processed within it, via t_on_reply("​onreply_route_index"​).
 +
 +Core '​reply_route'​ block is executed before a possible **tm** '​onreply_route'​ block.
 +
 +<code c>
 +  request_route {
 +      lookup("​location"​);​
 +      t_on_reply("​LOGRPL"​);​
 +      if(!t_relay()) {
 +          sl_send_reply("​500",​ "​relaying failed"​);​
 +      }
 +  }
 +
 +  reply_route {
 +      if(!t_check_trans()) {
 +          drop;
 +      }
 +  }
 +
 +  onreply_route[LOGRPL] {
 +      if(status=~"​1[0-9][0-9]"​) {
 +           ​log("​provisional response\n"​);​
 +      }
 +  }
 +</​code>​
 +==== onsend_route ====
 +
 +The route is executed in when a SIP request is sent out. Only a limited number of commands are allowed (drop, if + all the checks, msg flag manipulations,​ send(), log(), textops::​search()).
 +
 +In this route the final destination of the message is available and can be checked (with snd_ip, snd_port, to_ip, to_port, snd_proto, snd_af).
 +
 +This route is executed only when forwarding requests - it is not executed for replies, retransmissions,​ or locally generated messages (e.g. via fifo uac).
 +
 +Example:
 +
 +<code c>
 +  onsend_route {
 +    if(to_ip==1.2.3.4 && !isflagset(12)){
 +      log(1, "​message blocked\n"​);​
 +      drop;
 +    }
 +  }
 +</​code>​
 +
 +  * snd_ip, snd_port - behave like src_ip/​src_port,​ but contain the ip/port Kamailio will use to send the message
 +  * to_ip, to_port - like above, but contain the ip/port the message will be sent to (not to be confused with dst_ip/​dst_port,​ which are the destination of the original received request: Kamailio'​s ip and port on which the message was received)
 +  * snd_proto, snd_af - behave like proto/af but contain the protocol/​address family that Kamailio will use to send the message
 +  * msg:len - when used in an onsend_route,​ msg:len will contain the length of the message on the wire (after all the changes in the script are applied, Vias are added a.s.o) and not the lentgh of the original message.
 +
 +==== event_route ====
 +
 +Generic type of route executed when specific events happen.
 +
 +Prototype: event_route[groupid:​eventid]
 +  * groupid - should be the name of the module that triggers the event
 +  * eventid - some meaningful short text describing the event
 +
 +Implementations:​
 +
 +  * **event_route[core:​worker-one-init]** - executed by core after the first udp sip worker process executed the child_init() for all modules, before starting to process sip traffic
 +    * note that due to forking, other sip workers can get faster to listening for sip traffic
 +
 +<code c>
 +event_route[core:​worker-one-init] {
 +        xlog("​L_INFO","​Hello world\n"​);​
 +}
 +</​code>​
 +
 +  * **event_route[htable:​mod-init]** - executed by **htable** module after all modules have been initialised. Good for initialising values in hash tables.
 +<code c>
 +modparam("​htable",​ "​htable",​ "​a=>​size=4;"​)
 +
 +event_route[htable:​mod-init] {
 +  $sht(a=>​calls-to::​10.10.10.10) = 0;
 +  $sht(a=>​max-calls-to::​10.10.10.10) = 100;
 +}
 +
 +request_route {
 +  if(is_method("​INVITE"​) && !has_totag())
 +  {
 +    switch($rd) {
 +      case "​10.10.10.10":​
 +        lock("​calls-to::​10.10.10.10"​);​
 +        $sht(a=>​calls-to::​10.10.10.10) =
 +            $sht(a=>​calls-to::​10.10.10.10) + 1;
 +        unlock("​calls-to::​10.10.10.10"​);​
 +        if($sht(a=>​calls-to::​10.10.10.10)>​$sht(a=>​max-calls-to::​10.10.10.10))
 +        {
 +           ​sl_send_reply("​500",​ "To many calls to .10");
 +           exit;
 +        }
 +      break;
 +      ...
 +    }
 +  }
 +}
 +</​code>​
 +  * **event_route [tm:​local-request]** - executed on locally generated requests.
 +<code c>
 +event_route [tm:​local-request] { # Handle locally generated requests
 +  xlog("​L_INFO",​ "​Routing locally generated $rm to <​$ru>​\n"​);​
 +  t_set_fr(10000,​ 10000);
 +}
 +</​code>​
 +
 +  * **event_route [tm:​branch-failure]** - executed on all failure responses.
 +<code c>
 +event_route [tm:​failure-branch] { # Handle failure response
 +  xlog("​L_INFO",​ "​Handling $T_reply_code response to $rm to <​$ru>​\n"​);​
 +  if (t_check_status("​430"​)) { # Outbound flow failed
 +    unregister("​location",​ "​$tu",​ "​$T_reply_ruid"​);​
 +    if (t_next_contact_flow()) {
 +      t_relay();
 +    }
 +  }
 +}
 +</​code>​
 +
 +===== Script Statements =====
 +
 +==== if ====
 +IF-ELSE statement
 +
 +Prototype:
 +
 +<​code>​
 +    if(expr) {
 +       ​actions;​
 +    } else {
 +       ​actions;​
 +    }
 +</​code>​
 +
 +The '​expr'​ should be a valid logical expression.
 +
 +The logical operators that can be used in '​expr':​
 +
 +<​code>​
 +  ==      equal
 +  !=      not equal
 +  =~      regular expression matching: Note: Posix regular expressions will be used, e.g. use [[:​digit:​]]{3} instead of \d\d\d
 +  !~      regular expression not-matching (NOT PORTED from Kamailio 1.x, use '!(x =~ y)')
 +  >       ​greater
 +  >=      greater or equal
 +  <       less
 +  <=      less or equal
 +  && ​     logical AND
 +  ||      logical OR
 +  !       ​logical NOT
 +  [ ... ] test operator - inside can be any arithmetic expression
 +</​code>​
 +
 +Example of usage:
 +
 +    if(is_method("​INVITE"​))
 +    {
 +        log("​this sip message is an invite\n"​);​
 +    } else {
 +        log("​this sip message is not an invite\n"​);​
 +    }
 +
 +
 +==== switch ====
 +
 +SWITCH statement - it can be used to test the value of a pseudo-variable. ​
 +
 +IMPORTANT NOTE: '​break'​ can be used only to mark the end of a '​case'​ branch (as it is in shell scripts). If you are trying to use '​break'​ outside a '​case'​ block the script will return error -- you must use '​return'​ there.
 +
 +
 +Example of usage:
 +<​code>​
 +    route {
 +        route(1);
 +        switch($retcode)
 +        {
 +            case -1:
 +                log("​process INVITE requests here\n"​);​
 +            break;
 +            case 1:
 +                log("​process REGISTER requests here\n"​);​
 +            break;
 +            case 2:
 +            case 3:
 +                log("​process SUBSCRIBE and NOTIFY requests here\n"​);​
 +            break;
 +            default:
 +                log("​process other requests here\n"​);​
 +       }
 +
 +        # switch of R-URI username
 +        switch($rU)
 +        {
 +            case "​101":​
 +                log("​destination number is 101\n"​);​
 +            break;
 +            case "​102":​
 +                log("​destination number is 102\n"​);​
 +            break;
 +            case "​103":​
 +            case "​104":​
 +                log("​destination number is 103 or 104\n"​);​
 +            break;
 +            default:
 +                log("​unknown destination number\n"​);​
 +       }
 +    }
 +
 +    route[1]{
 +        if(is_method("​INVITE"​))
 +        {
 +            return(-1);
 +        };
 +        if(is_method("​REGISTER"​))
 +            return(1);
 +        }
 +        if(is_method("​SUBSCRIBE"​))
 +            return(2);
 +        }
 +        if(is_method("​NOTIFY"​))
 +            return(3);
 +        }
 +        return(-2);
 +    }
 +</​code>​
 +
 +NOTE: take care while using '​return'​ - '​return(0)'​ stops the execution of the script.
 +
 +
 +==== while ====
 +
 +while statement
 +
 +Example of usage:
 +    ​
 +    $var(i) = 0;
 +    while($var(i) < 10)
 +    {
 +        xlog("​counter:​ $var(i)\n"​);​
 +        $var(i) = $var(i) + 1;
 +    }
 +
 +===== Script Operations =====
 +
 +Assignments together with string and arithmetic operations can be done directly in configuration file.
 +==== Assignment ====
 +
 +Assignments can be done like in C, via '​='​ (equal). The following pseudo-variables can be used in left side of an assignment:
 +  * Unordered List Item AVPs - to set the value of an AVP
 +  * script variables ($var(...)) -  to set the value of a script variable
 +  * shared variables ($shv(...))
 +  * $ru - to set R-URI
 +  * $rd - to set domain part of R-URI
 +  * $rU - to set user part of R-URI
 +  * $rp - to set the port of R-URI
 +  * $du - to set dst URI
 +  * $fs - to set send socket
 +  * $br - to set branch
 +  * $mf - to set message flags value
 +  * $sf - to set script flags value
 +  * $bf - to set branch flags value
 +
 +<​code>​
 +$var(a) = 123;
 +</​code>​
 +
 +For avp's there a way to remove all values and assign a single value in one statement (in other words, delete existing AVPs with same name, add a new one with the right side value). This replaces the := assignment operator from kamailio < 3.0.
 +<​code>​
 +$(avp(i:​3)[*]) = 123;
 +$(avp(i:​3)[*]) = $null;
 +</​code>​
 +
 +==== String Operations ====
 +For strings, '​+'​ is available to concatenate.
 +
 +<​code>​
 +$var(a) = "​test";​
 +$var(b) = "​sip:"​ + $var(a) + "​@"​ + $fd;
 +</​code>​
 +==== Arithmetic Operations ====
 +
 +For numbers, one can use:
 +  * + : plus
 +  * - : minus
 +  * / : divide
 +  * * : multiply
 +  * % : modulo (Kamailio uses '​mod'​ instead of '​%'​)
 +  * | : bitwise OR
 +  * & : bitwise AND
 +  * ^ : bitwise XOR
 +  * ~ : bitwise NOT
 +  * <​nowiki><<</​nowiki>​ : bitwise left shift
 +  * <​nowiki>>></​nowiki>​ : bitwise right shift
 +
 +Example:
 +
 +<​code>​
 +$var(a) = 4 + ( 7 & ( ~2 ) );
 +</​code>​
 +
 +NOTE: to ensure the priority of operands in expression evaluations do use __parenthesis__.
 +
 +Arithmetic expressions can be used in condition expressions.
 +
 +<​code>​
 +if( $var(a) & 4 )
 +    log("​var a has third bit set\n"​);​
 +</​code>​
 +
 +===== Operators =====
 +
 +  - type casts operators: (int), (str).
 +  - string comparison: eq, ne
 +  - integer comparison: ieq, ine 
 +
 +Note: The names are not yet final (use them at your own risk). Future version might use ==/!= only for ints (ieq/ine) and eq/ne for strings (under debate). They are almost equivalent to == or !=, but they force the conversion of their operands (eq to string and ieq to int), allowing among other things better type checking on startup and more optimizations.
 +
 +Non equiv. examples:
 +
 +0 == ""​ (true) is not equivalent to 0 eq ""​ (false: it evaluates to "​0"​ eq ""​).
 +
 +"​a"​ ieq "​b"​ (true: (int)"​a"​ is 0 and (int)"​b"​ is 0) is not equivalent to "​a"​ == "​b"​ (false).
 +
 +Note: internally == and != are converted on startup to eq/​ne/​ieq/​ine ​ whenever possible (both operand types can be safely determined at start time and they are the same). ​
 +
 +  - Kamailio tries to guess what the user wanted when operators that support multiple types are used on different typed operands. In general convert the right operand to the type of the left operand and then perform the operation. Exception: the left operand is undef. This applies to the following operators: +, == and !=.
 +     ​Special case: undef as left operand:
 +     For +: undef + expr -> undef is converted to string => ""​ + expr.
 +     For == and !=:   undef == expr -> undef is converted to type_of expr.
 +     If expr is undef, then undef == undef is true (internally is converted
 +     to string).
 +
 +  - expression evaluation changes: Kamailio will auto-convert to integer or string in function of the operators: ​
 +       ​int(undef)==0, ​ int(""​)==0,​ int("​123"​)==123,​ int("​abc"​)==0
 +       ​str(undef)=="",​ str(123)=="​123"​.
 +
 +  - script operators for dealing with empty/​undefined variables
 +      defined expr - returns true if expr is defined, and false if not.
 +                     Note: only a standalone avp or pvar can be
 +                     ​undefined,​ everything else is defined.
 +      strlen(expr) - returns the lenght of expr evaluated as string.
 +      strempty(expr) - returns true if expr evaluates to the empty
 +                       ​string (equivalent to expr==""​).
 +      Example: if (defined $v && !strempty($v)) $len=strlen($v);​
 +
cookbooks/5.2.x/core.1572390976.txt.gz ยท Last modified: 2019/10/30 00:16 by joelsdc