Monitoring SIP server status

The aim of this document is to provide information about how to monitor the status of SIP servers with which your machine interacts with and how to make handling decisions based on their status using lib_srv_qualifier.js (https://github.com/yatevoip/yate-common/blob/master/scripts/lib_srv_qualifier.js) from yate-common (https://github.com/yatevoip/yate-common).

Enabling functionality

For this, in your Yate machine, you need to have enabled a script that loads and configures lib_srv_qualifier.js from SVN/yate-common. The script should look like this:

conf_name = “my_sip_qual”;

module_name = “my_sip_qual”;

 

Server.type = “SIP”;

 

#require “lib_srv_qualifier.js”

 

qualifier_init(true);

 

/* vi: set ts=8 sw=4 sts=4 noet: */

where:

  •  conf_name specifies the file to use for configuration.
  • module_name specifies the name of the module and it is used in debug messages and in filtering Yate messages.
  • Server.type specifies what kind of monitoring you want. Options are SIP and HTTP. For this case, SIP is the needed option.

In YateUCN, there is such a script that monitors SIP servers that is loaded by default. That script is  ucn_sip_qual.

How it works

In order to determine the availability status of a SIP server, the script generates at the configured interval of time a SIP OPTIONS request for a server from its list of monitored servers. The request is generated by using ‘xsip.generate’ message. The server for which the request is generates is picked using round-robin, so every number_of_servers * check_interval seconds, that server is checked. The server is considered to be available if the response to SIP OPTIONS is in the 2xx range.

 Upon receiving the response to the SIP options request, if there is a transition from one state to another (e.g up → down / down → up) the script will generate a notification message that looks like this:

Sniffed ‘xsip.qualify’ time=1604320653.400904

  thread=0x6e2a3d0 ‘Engine Worker’

  data=(nil)

  retval='(null)’

  param[‘server’] = ‘192.168.168.139’

  param[‘name’] = ‘sip_139’

  param[‘available’] = ‘false’

where:

  • server is the SIP URI/address
  • name is the name of the configuration section for this server
  • available denotes the status of the server: true for up, false otherwise.

This message can then be caught by other modules in Yate that are interested in the state of SIP servers.

Configuration

Once the script in loaded, it will read as configuration the file with the name set from conf_name.

This configuration file specifies what servers should be monitored.

The configuration file for SIP monitoring should look like this:

[general]                                                                                                                                                                                                   

check_interval=60                                                                                                                                                                                           

trans_count=3                                                                                                                                                                                               

                                                                                                                                                                                                            

[server gw139]                                                                                                                                                                                            

;enable=no                                                                                                                                                                                                  

uri= 192.168.168.139                                                                                                                                                                                          

conn_id=core                                                                                                                                                                                                

trans_count=2                                                                                                                                                                                               

                                                                                                                                                                                                            

[server 192.168.168.241]                                                                                                                                                                                    

;enable=no                                                                                                                                                                                                  

line=sip241                                                                                                                                                                                                 

                                                                                                                                                                                                            

[server 999@192.168.168.11]                                                                                                                                                                                  

conn_id=core

The general section configures:

  • check_interval: interval in seconds at which the script picks the server to check
  • trans_count: number of SIP re-transmissions for SIP OPTIONS

Every sections that starts with server configures a server to be monitored. The configuration parameters for each section are:

  • enable: boolean that enables or disables the checking of this servers
  • uri: the SIP URI to use in the SIP OPTIONS message. If not provided, URI will be taken to be the name of the configuration sections without the ‘server ‘ prefix
  • conn_id: the SIP listener to use for sending the SIP OPTIONS message towards the SIP server. Parameters line or conn_id must be present in a valid configuration
  • line: the SIP account to use for sending the SIP OPTIONS message towards the SIP server. This is usually configured via accfile.conf.  Parameters line or conn_id must be present in a valid configuration
  • trans_count: this is the same parameter from the general configuration section and it is used to override the value from there.

Changes of parameters are applied on reload.

Using SIP monitoring for routing

The xsip.qualify messages sent by the SIP qualifier script can be used for making routing decisions for SIP calls based on the availability of the server. The script below provides an example on how to route a SIP call in round-robin fashion to available servers.

Engine.debugName(“sip_qual_routing”);

Message.trackName(“sip_qual_routing”);

 

// list of servers used to route a call, all considered to be down initially

sip_servers = {

   “192.168.168.139” : false,

   “192.168.168.241” : false,

   “192.168.168.1” : false,

};

 

avail_srv = []; // list of servers that are available

idx = 0;

 

function onXsipQualify(msg)

{

   if(sip_servers[msg.server] == undefined)

      return;

   sip_servers[msg.server] = msg.available;

   // rebuild the list of available servers

   avail_srv = [];

   for (var s in sip_servers) {

      if (sip_servers[s])

         avail_srv.push(s);

   }

   Engine.debug(Engine.DebugInfo,”Available SIP servers:”,avail_srv.join());

   return false; // let others to handle the message too

}

 

function onRoute(msg)

{

   if (msg.called.startsWith(“123”)) {

      if (!avail_srv.length) // no available servers

         return false;

      msg.retValue(“sip/sip:” + msg.called + “@” + avail_srv[idx++ % avail_srv.length]);

      return true;

   }

   return false;

}

 

Message.install(onXsipQualify,”xsip.qualify”,50);

Message.install(onRoute,”call.route”,50);

This is a piece of log showing the xsip.qualify messages being caught by the script and routing of a call:

Sniffed ‘xsip.qualify’ time=1604327107.569913

  thread=0x6e2a3b0 ‘Engine Worker’

  data=(nil)

  retval='(null)’

  param[‘server’] = ‘192.168.168.1’

  param[‘name’] = ‘192.168.168.1’

  param[‘available’] = ‘true’

2020-11-02_14:25:07.578010 <sip_qual_routing:INFO> Available SIP servers: 192.168.168.241,192.168.168.1

Returned false ‘xsip.qualify’ delay=0.011641

  thread=0x6e2a3b0 ‘Engine Worker’

  data=(nil)

  retval='(null)’

  param[‘server’] = ‘192.168.168.1’

  param[‘name’] = ‘192.168.168.1’

  param[‘available’] = ‘true’

  param[‘handlers’] = ‘sip_qual_routing:50’

Sniffed ‘call.route’ time=1604327187.849314

  thread=0x7f60a00017c0 ‘RManager Connection’

  data=(nil)

  retval='(null)’

  param[‘module’] = ‘tone’

  param[‘cdrtrack’] = ‘false’

  param[‘called’] = ‘123’

  param[‘caller’] = ‘tone/dial’

Returned true ‘call.route’ delay=0.002136

  thread=0x7f60a00017c0 ‘RManager Connection’

  data=(nil)

  retval=’sip/sip:123@192.168.168.241′

  param[‘module’] = ‘tone’

  param[‘cdrtrack’] = ‘false’

  param[‘called’] = ‘123’

  param[‘caller’] = ‘tone/dial’

  param[‘handlers’] = ‘javascript:15,regexroute:40,cdrbuild:50,sip_qual_routing:50’ 

Using SIP qualifier with regexp

In order to use SIP qualifier with regexp, we need:

  1. Store/detect SIP server availability/status

To store the last detected SIP server status we need to add a regexroute routing rule to equipment:

It can be added from YateMMI in My Network -> Routing -> Equipment Type: select from dropdown -> Add

name : sip_qual

  [extra]

  xsip_qualify=120

 

  [xsip_qualify]

  ; Store last detected SIP server status in variable srv_IP_address, to be used later in [default] routing section

  .*=;$srv_${server}=${available}

Monitoring SIP server sip-qual example

      2. Round-robin SIP servers that are up using regexp route rule

This can be also done from YateMMI -> Equipment -> pick equipment ->Edit -> Routing -> Add

name : round_robin

  [default]

  ; Build a list of active servers, delete any previous value of variable_srv

  ; we will use YateUCN name and [default] routing section as examples

  .*=;srv=

  ; example: YateUCN1

  $(srv_192.168.168.139)=;srv=${srv},192.168.168.139

  ; example: YateUCN2

  $(srv_192.168.168.241)=;srv=${srv},192.168.168.241

  ; Round-robin SIP servers that are up on YateUCN1 or YateUCN2 from YateUCN3

  ${srv}.=sip/sip:${called}${npdi}${rn}@$(index,$tkidx${srv})$()user=phone;srv;npdi;rn

  ; if no servers are available, throw an error and stop call routing

  ${srv}^$-;error=service-unavailable;reason=All gateways down

Monitoring SIP server round-robin example