# &adminguide;

## Overview

Useful extensions for the server configuration.

The cfgutils module can be used to introduce randomness to the behaviour of the server. It provides setup functions and the rand_event function. This function return either true or false, depending on a random value and a specified probability. E.g. if you set via fifo or script a probability value of 5%, then 5% of all calls to rand_event will return false. The pseudovariable $RANDOM could be used to introduce random values e.g. into a SIP reply.

The benefit of this module is the probability of the decision can be manipulated by external applications such as web interface or command line tools. The probability must be specified as percent value, ranging from 0 to 100.

The module exports commands to FIFO server that can be used to change the global settings via FIFO interface. The FIFO commands are: set_prob, reset_prob and get_prob.

This module can be used for simple load-shedding, e.g. reply 5% of the Invites with a 503 error and a adequate random Retry-After value.

The module provides as well functions to delay the execution of the server. The functions sleep and usleep could be used to let the server wait a specific time interval.

It can also hash the config file used from the server with a (weak) cryptographic hash function on startup. This value is saved and can be later compared to the actual hash, to detect modifications of this file after the server start. This functions are available as the FIFO commands check_config_hash and get_config_hash.

## Dependencies

The module depends on the following modules (in the other words the listed modules must be loaded before this module):

- none

## Exported Parameters

### `initial_probability` (string)

The initial value of the probability.

Default value is 10.

#### `initial_probability` parameter usage

    modparam("cfgutils", "initial_probability", 15)

### `hash_file` (string)

The config file name for that a hash value should be calculated on startup.

There is no default value, is no parameter is given the hash functionality is disabled.

#### `hash_file` parameter usage

    modparam("cfgutils", "hash_file", "/etc/opensips/opensips.cfg")

### `shvset` (string)

Set the value of a shared variable ($shv(name)). The parameter can be set many times.

The value of the parameter has the format: _name_ '=' _type_ ':' _value_

- _name_: shared variable name

- _type_: type of the value

  - i: integer value

  - s: string value

- _value_: value to be set

Default value is NULL.

#### `shvset` parameter usage

    ...
    modparam("cfgutils", "shvset", "debug=i:1")
    modparam("cfgutils", "shvset", "pstngw=s:sip:10.10.10.10")
    ...

### `varset` (string)

Set the value of a script variable ($var(name)). The parameter can be set many times.

The value of the parameter has the format: _name_ '=' _type_ ':' _value_

- _name_: shared variable name

- _type_: type of the value

  - i: integer value

  - s: string value

- _value_: value to be set

Default value is NULL.

#### `varset` parameter usage

    ...
    modparam("cfgutils", "varset", "init=i:1")
    modparam("cfgutils", "varset", "gw=s:sip:11.11.11.11;transport=tcp")
    ...

### `lock_pool_size` (integer)

The number of dynamic script locks to be allocated at &osips; startup. This number must be a power of 2. (i.e. 1, 2, 4, 8, 16, 32, 64 ...)

Note that the lock_pool_size parameter only affects the number of dynamic locks created at startup. The pool of static locks only depends on the number of unique static strings supplied throughout the script to the set of static lock functions.

Default value is 32.

#### Setting lock_pool_size module parameter

    modparam("cfgutils", "lock_pool_size", "64")

## Exported Functions

### `rand_event([probability])`

Return true or false, depending on a random value and a probability value. If probability parameter is given, it will override the global parameter set by rand_set_prob() function.

#### `rand_event()` usage

    ...
    if (rand_event()) {
      append_to_reply("Retry-After: 120\n");
      sl_send_reply("503", "Try later");
      exit;
    };
    # normal message processing follows
    ...

### `rand_set_prob(probabiltiy)`

Set the probability of the decision.

probability can have a value from the range 0..99.

#### `rand_set_prob()` usage

    ...
    rand_set_prob("4");
    ...

### `rand_reset_prob()`

Reset the probability back to the inital value.

#### `rand_reset_prob()` usage

    ...
    rand_reset_prob();
    ...

### `rand_get_prob()`

Return the current probability setting, e.g. for logging purposes.

#### `rand_get_prob()` usage

    ...
    rand_get_prob();

### `sleep(time)`

Waits "time" seconds.

Meaning of the parameters is as follows:

- time - Time to wait in seconds. String may be a pseudovariable. In case that variable does not contain a numerical value, it is evaluated to zero seconds.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `sleep` usage

    ...
    sleep("1");
    ...
    $avp(secs)="10";
    sleep("$avp(secs)");
    ...

### `usleep(time)`

Waits "time" micro-seconds.

Meaning of the parameters is as follows:

- time - Time to wait in micro-seconds. The string may contain a pseudovariable. In case that pseudovar does not contain a numerical value, it is evaluated to zero seconds.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `usleep` usage

    ...
    usleep("500000"); # sleep half of sec
    ...

### `abort()`

Debugging function that aborts the server. Depending on the configuration of the server a core dump will be created.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `abort` usage

    ...
    abort();
    ...

### `pkg_status()`

Debugging function that dumps the status for the private (PKG) memory. This information is logged to the default log facility, depending on the general log level and the memlog setting. You need to compile the server with activated memory debugging to get detailed informations.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `pkg_status` usage

    ...
    pkg_status();
    ...

### `shm_status()`

Debugging function that dumps the status for the shared (SHM) memory. This information is logged to the default log facility, depending on the general log level and the memlog setting. You need to compile the server with activated memory debugging to get detailed informations.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `shm_status` usage

    ...
    shm_status();
    ...

### `set_count(pvar name, result pvar name)`

Function that counts the values of a pseudovariable. It makes sense to call this function only for pseudovariables that can take more values (avp, headers).

The result is returned in the second parameter.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `set_count` usage

    ...
    set_count("$avp(10)", "$avp(result)");
    ...

### `set_select_weight(pseudovarible_name)`

This function selects an element from a set formed by the values of the pseudovariable name given as parameter. It applies the genetic algorithm - roulette-wheel selection to choose an element from a set. The probability of selecting a certain element is proportionate with its weight. It will return the index of that selected element.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `set_select_weight` usage

    ...
    $avp(21) = set_select_weight("$avp(10)");
    ...

### `ts_usec_delta(t1_sec, t1_usec, t2_sec, t2_usec, delta)`

This function returns the difference between two timestamps, specified in seconds and microseconds. The result is returned in the last parameter, expressed in microseconds.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

#### `ts_usec_delta` usage

    ...
    ts_usec_delta("$avp(10)", "$avp(20)", "10", "300", "$avp(result)");
    ...

### `check_time_rec(time_string)`

The function returns a positive value if the specified time recurrence string matches the current time, or a negative value otherwise.

The syntax of each field is identical to the corresponding field from RFC 2445.

This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE.

Meaning of the parameters is as follows:

- time_string - Time recurrence string which will be matched against the current time. Its fields are separated by "|" and the order in which they are given is: "dtstart | dtend | duration | freq | until | interval | byday | bymday | byyday | byweekno | bymonth". None of the fields following "freq" is used unless "freq" is defined. If the string ends in multiple null fields, they can all be ommited.

  The time_string parameter can have the following types:

  - string - the time recurrence string is statically assigned

  - pvar - the string is the value of an existing pseudo-variable (as string value)

#### `check_time_rec` usage

    ...
    # Only passing if still in 2012
    if (check_time_rec("20120101T000000|20121231T235959")) {
    	xlog("Current time matches the given interval\n");
    }
    ...
    # Only passing if less than 30 days have passed from "dtstart"
    if (check_time_rec("20121101T000000||p30d")) {
    	xlog("Current time matches the given interval\n");
    }
    ...

### `get_static_lock(string)`

The function obtains the index of a specific lock (predetermined in the fixup phase of the OpenSIPS script) and attempts to acquire it. In case the lock is taken by another process, script execution will halt until the lock is released. Attempting to acquire the lock a second time by the same process, without releasing it first, will result in a deadlock.

The static lock functions guarantee that two different strings will never point to the same lock, thus avoiding introducing unnecessary (and transparent!) synchronization between processes. Their disadvantage is the nature of their parameters (static strings), making them inappropriate in certain scenarios.

Meaning of the parameters is as follows:

- string - String to be used in order to obtain the index of a static lock. The string parameter can have the following types:

  - string - the string is statically assigned

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE.

#### `get_static_lock` usage

    # acquire and release a static lock
    ...
    get_static_lock("Zone_1");
    ...
    release_static_lock("Zone_1");
    ...

### `release_static_lock(string)`

The function obtains the index of a specific lock (predetermined in the fixup phase of the OpenSIPS script) and releases it. Nothing will happen if the lock is not acquired.

Meaning of the parameters is as follows:

- string - String to be used in order to obtain the index of a static lock. The string parameter can have the following types:

  - string - the string is statically assigned

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE|EVENT_ROUTE.

#### `release_static_lock` usage

    # acquire and release a static lock
    ...
    get_static_lock("Zone_1");
    ...
    release_static_lock("Zone_1");
    ...

### `get_dynamic_lock(string)`

The function obtains the index of a lock from the pool by performing a hash function on the given variable string and attempts to acquire it. In case the lock is taken by another process, script execution will halt until the lock is released. Attempting to acquire the lock a second time by the same process, without releasing it first, will result in a deadlock.

The dynamic lock functions have the advantage of allowing string pseudo-variables to be given as parameters, but the drawback to this is that two strings may have the same hashed value, thus pointing to the same lock. As a consequence, either two totally separate regions of the script will be synchronized (they will not execute in parallel), or a process could end up in a deadlock by acquiring two locks in a row on two different (but equally hashed) strings. To address the latter issue, use the strings_share_lock() function to test if two strings generate equal hash values.

Meaning of the parameters is as follows:

- string - String to be hashed in order to obtain the index of a lock from the pool. The string parameter can have the following types:

  - pvar - the string is the value of an existing pseudo-variable (as string value)

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE|EVENT_ROUTE.

#### `get_dynamic_lock` usage

    ...
    # acquire and release a dynamic lock on the "Call-ID" Header of a SIP message
    if (!get_dynamic_lock("$ci")) {
    	xlog("Error while getting dynamic lock!\n");
    }
    ...
    if (!release_dynamic_lock("$ci") {
    	xlog("Error while releasing dynamic lock!\n");
    }
    ...

### `release_dynamic_lock(string)`

The function obtains the index of a lock from the pool by performing a hash function on the given variable string and releases it. Nothing will happen if the lock is not acquired.

Meaning of the parameters is as follows:

- string - String to be hashed in order to obtain the index of a lock from the pool. The string parameter can have the following types:

  - pvar - the string is the value of an existing pseudo-variable (as string value)

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE|EVENT_ROUTE.

#### `release_dynamic_lock` usage

    ...
    # acquire and release a dynamic lock on the "Call-ID" Header of a SIP message
    if (!get_dynamic_lock("$ci")) {
    	xlog("Error while getting dynamic lock!\n");
    }
    ...
    if (!release_dynamic_lock("$ci") {
    	xlog("Error while releasing dynamic lock!\n");
    }
    ...

### `strings_share_lock(string1, string2)`

A function used to test if two strings will generate the same hash value. Its purpose is to prevent deadlocks resulted when a process successively acquires two dynamic locks on two strings which happen to point to the same lock.

Theoretically, the chance of two strings generating the same hash value decreases proportionally to the increase of the lock_pool_size parameter. In other words, the more dynamic locks you configure the module with, the higher the chance that all individual protected regions of your script will run in parallel, without waiting for each other.

Meaning of the parameters is as follows:

- string1, string2 - Strings which will have their hash values compared. The string parameters can have the following types:

  - string - statically assigned

  - pvar - values of existing pseudo-variables (as string values)

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE, LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE|EVENT_ROUTE.

#### `strings_share_lock` usage

    ...
    # Proper way of acquiring two dynamic locks successively
    if (!get_dynamic_lock("$avp(1)")) {
    	xlog("Error while getting dynamic lock!\n");
    }

    if (!strings_share_lock("$avp(1)", "$avp(2)") {
    	if (!get_dynamic_lock("$avp(2)")) {
    		xlog("Error while getting dynamic lock!\n");
    	}
    }
    ...
    if (!strings_share_lock("$avp(1)", "$avp(2)") {
    	if (!release_dynamic_lock("$avp(2)") {
    		xlog("Error while releasing dynamic lock!\n");
    	}
    }

    if (!release_dynamic_lock("$avp(1)") {
    	xlog("Error while releasing dynamic lock!\n");
    }
    ...

## Exported Asyncronous Functions

### `sleep(seconds)`

Waits a number of seconds. This function does exactly the same as sleep_sync, but in an asynchronous way. The script execution is suspended until the waiting is done; then OpenSIPS resumes the script execution via the resume route.

To read and understand more on the asynchronous functions, how to use them and what are their advantages, please refer to the OpenSIPS online Manual.

#### `async sleep` usage

    {
    ...
    async( sleep("5"), after_sleep );
    }

    route[after_sleep] {
    ...
    }

### `usleep(seconds)`

Waits a number of micro-seconds. This function does exactly the same as usleep_sync, but in an asynchronous way. The script execution is suspended until the waiting is done; then OpenSIPS resumes the script execution via the resume route.

To read and understand more on the asynchronous functions, how to use them and what are their advantages, please refer to the OpenSIPS online Manual.

#### `async usleep` usage

    {
    ...
    async( usleep("1000"), after_usleep );
    }

    route[after_usleep] {
    ...
    }

## MI Commands

### `rand_set_prop`

Set the probability value to the given parameter. The parameter should be a percent value.

The parameter value must be a number from 0 to 99.

#### `rand_set_prob` usage

    ...
    $ opensipsctl fifo rand_set_prob 10
    ...

### `rand_reset_prob`

Reset the probability value to the inital start value.

This command don't need a parameter.

#### `rand_reset_prob` usage

    ...
    $ opensipsctl fifo rand_reset_prob
    ...

### `rand_get_prob`

Return the actual probability setting.

The function return the actual probability value.

#### `rand_get_prob` usage

    ...
    $ opensipsctl fifo get_prob
    The actual probability is 50 percent.
    ...

### `check_config_hash`

Check if the actual config file hash is identical to the stored one.

The function returns 200 OK if the hash values are identical, 400 if there are not identical, 404 if no file for hashing has been configured and 500 on errors. Additional a short text message is printed.

#### `check_config_hash` usage

    ...
    $ opensipsctl fifo check_config_hash
    The actual config file hash is identical to the stored one.
    ...

### `get_config_hash`

Return the stored config file hash.

The function returns 200 OK and the hash value on success or 404 if no file for hashing has been configured.

#### `get_config_hash` usage

    ...
    $ opensipsctl fifo get_config_hash
    1580a37104eb4de69ab9f31ce8d6e3e0
    ...

### `shv_set`

Set the value of a shared variable ($shv(name)).

Parameters:

- _name_: shared variable name

- _type_: type of the value

  - int: integer value

  - str: string value

- _value_: value to be set

MI FIFO Command Format:

    		:shv_set:_reply_fifo_file_
    		_name_
    		_type_
    		_value_
    		_empty_line_

#### `shv_set` usage

    ...
    $ opensipsctl fifo shv_set debug int 0
    ...

### `shv_get`

Get the value of a shared variable ($shv(name)).

Parameters:

- _name_: shared variable name. If this parameter is missing, all shared variables are returned.

MI FIFO Command Format:

    		:shv_get:_reply_fifo_file_
    		_name_
    		_empty_line_

#### `shv_get` usage

    ...
    $ opensipsctl fifo shv_get debug
    $ opensipsctl fifo shv_get
    ...

## Exported pseudo-variables

### `$env(name)`

This PV provides access to the environment variable 'name'.

#### `env(name) pseudo-variable` usage

    ...
    xlog("PATH environment variable is $env(PATH)\n");
    ...

### `$RANDOM`

Returns a random value from the [0 - 2^31) range.

#### `RANDOM pseudo-variable` usage

    ...
    $avp(10) = ($RANDOM / 16777216); # 2^24
    if ($avp(10) < 10) {
       $avp(10) = 10;
    }
    append_to_reply("Retry-After: $avp(10)\n");
    sl_send_reply("503", "Try later");
    exit;
    # normal message processing follows

### `$ctime(name)`

The PV provides access to broken-down time attributes.

The name can be:

- sec - return seconds (int 0-59)

- min - return minutes (int 0-59)

- hour - return hours (int 0-23)

- mday - return the day of month (int 0-59)

- mon - return the month (int 1-12)

- year - return the year (int, e.g., 2008)

- wday - return the day of week (int, 1=Sunday - 7=Saturday)

- yday - return the day of year (int, 1-366)

- isdst - return daylight saving time status (int, 0 - DST off, >0 DST on)

#### `ctime(name) pseudo-variable` usage

    ...
    if ($ctime(year) == 2008) {
    	xlog("request: $rm from $fu to $ru in year 2008\n");
    }
    ...

### `$shv(name)`

It is a class of pseudo-variables stored in shared memory. The value of $shv(name) is visible across all opensips processes. Each shv has single value and it is initialized to integer 0. You can use shvset parameter to initialize the shared variable. The module exports a set of MI functions to get/set the value of shared variables.

#### `shv(name) pseudo-variable` usage

    ...
    modparam("cfgutils", "shvset", "debug=i:1")
    ...
    if ($shv(debug) == 1) {
    	xlog("request: $rm from $fu to $ru\n");
    }
    ...