Registration Monitor

I thought I would post a modified version of a php script that I have been using since the days of the PIAF forum.

I have now updated it to check both sip and pjsip trunks and send an email if it detects a trunk that is not registered.

It has been tested on FreePBX 15 Asterisk 16 though the original code goes back to 2009.
indent preformatted text by 4 spaces

#!/usr/bin/php
<?php
/*
Checks registrations of both sip and pjsip trunks and sends an email if failure detected.

Originally Based on monitor_trunk.php from <https://github.com/reconwireless/freepbx-trunk-monitor>
Originally published by Nikol S ns at eyo.com.au 2009/11/02 04:31:29
Modified	13 May 2018 by Les Desser
			16 Mar 2021 by Les Desser - added new code for pjsip and completely restructured.
										Tested on FreePBX 15 Asterisk 16
To setup,
1. Change constants as appropriate
2. Put this file somewhere (eg. var/lib/asterisk/agi-bin/trunk_check_registered.php)
3. chmod it to 750(#chmod 750 monitor_trunk.php). Either owned by root or asterisk(#chown root.root monitor_trunk.php).
4. Edit crontab file in /var/spool/cron/ for appropriate user (root or asterisk), and add something like:
	  x/5 * * * * var/lib/asterisk/agi-bin/trunk_check_registered.php
   to the file. Last line in the cron file must have a carriage return!
   Above entry in the cron file will run the script every n minutes - change x to *
   
WARNING: This code is sensitive to possible layout changes to the output of the asterisk 'show' commands.
		 If the column position for the registration status changes then the calls to function analyse_status
		 need to be changed appropriately.
*/
# =========================================================
# Change these as necessary
	const K_EMAIL_ADDRESS = '[email protected]';
	const K_SLEEP =20;	# Short pause
	const K_LOG_FILE = '/tmp/debug.log';
	const K_ERROR_PREFIX = 'FreePBX Error: Trunk not Registered: ';
# =========================================================
# Problem registration texts are:
	const K_ARRAY_ERROR_TEXT = array(
				'Request Sent',
				'No Authentication',
				'Unregistered',
				'Failed',
				'Auth. Sent',
				'Rejected',
				'Timeout',
				'Unknown'
				);
# OK text
	const K_REGISTERED = "Registered";
# Common Message text
	const K_MSG_FAIL = " trunk failure. Current status:\r\n\r\n";
# 'show' command
	const K_SHOW_SIP   = '/usr/sbin/asterisk -rx "sip show registry"';
	const K_SHOW_PJSIP = '/usr/sbin/asterisk -rx "pjsip show registrations"';
# =========================================================
# Check both sip and pjsip
	check_all();
# =========================================================
function check_all() {
# Checks both sip and pjsip
# Each check returns both $show_reg_output and $state
# $show_reg_output is the output from the 'show' commands
# $state is either 'ok' or the failing line from $show_reg_output

# Check sip. Call returns ok or error text
	$state = check_sip($show_reg_output);
# If failed then send an email and continue checking pjsip
	if ($state != 'ok')	{send_alert_email(K_EMAIL_ADDRESS, $state, 'SIP'.K_MSG_FAIL.$show_reg_output);}

# Check pjsip. 
	$state = check_pjsip($show_reg_output);
	if ($state != 'ok')	{send_alert_email(K_EMAIL_ADDRESS, $state, 'PJSIP'.K_MSG_FAIL.$show_reg_output);}
}
# =========================================================
function check_sip(&$show_reg_output) {
# Check status of sip trunks
# Pass back $show_reg_output as needed in email
# Return 'ok' or state of failed trunk

# Column 4 (5th) contains the Status value for 'sip show..'
	$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# If all OK then return
	if ($state == 'ok') return $state;
# Wait for K_SLEEP seconds and try again.
	sleep(K_SLEEP);
	$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# If cleared up then return
	if ($state == 'ok')	return $state;
# Still a problem. Try a 'reload', wait K_SLEEP seconds and check again
	$ret = shell_exec('/usr/sbin/asterisk -rx "module reload chan_sip"');
	sleep(K_SLEEP);
	$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# All done.
	return $state;
}
# =========================================================
function check_pjsip(&$show_reg_output) {
# Check status of pjsip trunks
# Pass back $show_reg_output as needed in email
# Return 'ok' or state of failed trunk

	$show_reg_output = shell_exec('/usr/sbin/asterisk -rx "pjsip show registrations"');
# Column 3 (4th) contains the Status value for 'pjsip show..'
	return analyse_show_reg_output($show_reg_output, K_SHOW_PJSIP, 3);
}
# =========================================================
# Analyse the output from the 'show reg' comand
function analyse_show_reg_output(&$show_reg_output,  $show_command, $column_id) {
# $show_reg_output: multi-line output from the 'show' command
# $show_command: 'show' command to be executed
# $column_id: Column number (starting from 0) within $show_reg_output in which the actual Status value appears

# Get registration status report
	$show_reg_output = shell_exec($show_command);
# Treat nothing returned as an error as even if no trunks exist, the command should return: No objects found.
	if (strlen(trim($show_reg_output)) == 0) return "Registration status output is empty";
# Separate out each line of the report
	$lines = explode("\n", str_replace("\r\n", "\n", trim($show_reg_output)));
# Go through each line looking for a problem
	for ($i = 1; $i < count($lines) - 1; $i++) {
	  # Check for OK text - skip line if found 
		if (strpos($lines[$i], K_REGISTERED) !== false) continue;
	  # Check for specific error texts - return as bad when 1st error status text is found
		foreach (K_ARRAY_ERROR_TEXT as $txt) {if (strpos($lines[$i], $txt) !== false) return $txt;}
	  # No matching registered or failed text found
	  # Maybe there is an other status we do not know about - treat as an error
	  # Break line into parts
		$parts = preg_split('/\s+/', $lines[$i]);
	  # If there is no $column_id'th column then the line can be ignored.
		if (!isset($parts[$column_id])) continue;
	  # If the text is not empty, then we assume it is some other error status.
		if ($parts[$column_id] <> '') return "Unknown Registration status: " . $lines[$i];
	}
# All trunks are OK
	return 'ok';
}
# =========================================================
function send_alert_email($email_address, $subject, $email_content = '') {
	mail($email_address, K_ERROR_PREFIX.$subject, $email_content);
}
# =========================================================
	function writelog($log) {
		$x=file_put_contents(K_LOG_FILE, date('Y-m-d H:i:s')." UT: ".$log."\n", FILE_APPEND);
	}
# =========================================================
# Debug tool: route var_dump output to debug log
# Example of use: vardumptolog('xx $_REQUEST=',$_REQUEST);
	function vardumptolog($txt,$var) {
	  # Turn on output-buffering
		ob_start();
	  # Dump to buffer
		var_dump($var);
	  # Get dumped string
		$result =  ob_get_contents();
		ob_end_clean();
		writelog($txt."=".$result);
	}
?>
2 Likes

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.