#!/usr/bin/php
<?php
#
# Usage: update-siptrunks-status
#
# This script updates the sip_trunk.status field of all defined SIP Trunks.
#
# (C) Copyright 2018-2024, Bogen Communications LLC. All rights reserved.
#
require '/usr/local/bin/db_credentials' ;

# Set $debug to TRUE to enable echo output for debugging
$debug = FALSE;

if ($debug == FALSE) {
	mysqli_report(MYSQLI_REPORT_OFF);
}

$db = new mysqli($server, $user, $pass, $database);

if ($db->connect_errno > 0) {
	die('Unable to connect to database ['.$db->connect_error.']');
}

#
# Set trunks with sip_trunk.enabled=0 to "Disabled" status
#
setAllEnabledMatchToStatus($debug, $db, 0, "Disabled");

#
# Now fetch SIP trunks status from Asterisk and update SIP Trunks status field:
#
updateSipTrunksStatus($debug, $db, $server);

$db->close();

exit(0);

###############
# END OF MAIN #
###############

##################################################################################
# updateSipTrunksStatus() will fetch registration and contact status from Asterisk
##################################################################################

function updateSipTrunksStatus($debug, $db, $server)
{
	if (($socket = fsockopen($server,"5038",$errno,$errstr,30)) == FALSE)
	{
		if ($debug) echo "Server down, set status to unknown".PHP_EOL;

		#
		# Set all enabled SIP trunks to "Unknown" status
		#
		setAllEnabledMatchToStatus($debug, $db, 1, "Unknown");

		return;
	}

	#
	# Set all enabled SIP trunks to "Unknown" status
	#
	setAllEnabledMatchToStatus($debug, $db, 1, "Unknown");

        stream_set_timeout($socket, 15);

	# Read Asterisk Call Manager banner (e.g. "Asterisk Call Manager/7.0.0")
	$retstr=fgets($socket);

	fputs($socket, "Action: Login\r\nUserName: webui\r\nSecret: BogenNyq1\r\n\r\n");

	# Read "Response: Success"
	$retstr=fgets($socket);

	# Read "Message: Authentication accepted"
	$retstr=fgets($socket);

	fputs($socket, "Action: Command\r\n");

	fputs($socket, "Command: pjsip show registrations\r\n\r\n");

	# Read "Response: Success"
	$retstr=fgets($socket);

	# Strip "Output: " text from Asterisk 18.2.2 AMI output
	$retstr = str_replace("Output: ","",$retstr);

	$loopCount = 0;

        stream_set_timeout($socket, 1);

	#
	# Read pjsip registrations
	#
	while (($retstr != "No objects found.") && (strpos($retstr, "Objects found: ") === false))
	{
		$retstr=fgets($socket);

		if ($retstr === false) break;

		# Strip "Output: " text from Asterisk 18.2.2 AMI output
		$retstr = str_replace("Output: ","",$retstr);

		if ($debug) echo $retstr;

		# Look for e.q. "110/sip:10.10.5.56    110   Registered"
		if (preg_match("/\s*(\S*)\/(\S*)\s*(\S*)\s*(\S*)/",
				 $retstr, $parts))
		{
			if ($debug) echo "Trunk: $parts[1] Status: $parts[4]\n";

			updateStatus($debug, $db, $parts[1], $parts[4]);
		}

		# Prevent infinite loop
		if ($loopCount++ > 100) break;
	}

        stream_set_timeout($socket, 15);

	#
	# Look for HT813 SIP Trunks
	#
	fputs($socket, "Action: Command\r\n");

	fputs($socket, "Command: pjsip show contacts\r\n\r\n");

	# Read "Response: Success"
	$retstr=fgets($socket);

	# Strip "Output: " text from Asterisk 18.2.2 AMI output
	$retstr = str_replace("Output: ","",$retstr);

        stream_set_timeout($socket, 1);

	$loopCount = 0;

	while (($retstr != "No objects found.") && (strpos($retstr, "Objects found: ") === false))
	{
		$retstr=fgets($socket);

		if ($retstr === false) break;

		$retstr = str_replace("Output: ","",$retstr);

		if ($debug) echo $retstr;

		# Look for contacts where name starts with "ht813-"
		if (preg_match("/  Contact:  (.*)\/\S*( *)\S*( *)(\S*)\S*/", $retstr, $parts))
		{
			if ($debug) echo "Trunk: $parts[1] Status: $parts[4]\n";

			if (strpos($parts[1], "ht813-") === 0)
			{
				updateStatus($debug, $db, $parts[1], $parts[4]);
			}
		}

		# Prevent infinite loop
		if ($loopCount++ > 100) break;
	}

	fputs($socket, "Action: Logoff\r\n\r\n");

	$retstr=fgets($socket);

	$loopCount = 0;

	while (strpos($retstr,"Goodbye") === false)
	{
		$retstr=fgets($socket);

		if ($retstr === false) break;

		if ($debug) echo $retstr;

		if ($loopCount++ > 10) break;
	}

	fclose($socket);
}

#############################################################
#
# updateStatus - will update status of $trunk_name to $status
#
#############################################################

function updateStatus($debug, $db, $trunk_name, $status)
{
	$setFmt = "UPDATE sip_trunk set status='%s' WHERE name='%s'";
	$setSQL = sprintf($setFmt, $status, $trunk_name);

	if ($debug) echo $setSQL.PHP_EOL;
	if (!$result = $db->query($setSQL)) {
		echo "Error running query [".$db->error."]".PHP_EOL;
	}
}

###############################################################################
#
# setAllEnabledMatchToStatus - will set trunk status to $status for trunks with
#                              sip_trunk.enabled == $enabledMatch
#
###############################################################################

function setAllEnabledMatchToStatus($debug, $db, $enabledMatch, $status)
{
	#
	# Read sip_trunk table,
	# if sip_trunk.enabled = $enabledMatch, set status to $status
	#
	$sql = "SELECT enabled,name from sip_trunk";

	if (!$result = $db->query($sql)) {
		die('There was an error running the query ['.$db->error.']');
	}

	while ($row = $result->fetch_assoc())
	{
		if ($row['enabled'] == $enabledMatch) {
			$trunk_name = $row['name'];
			$trunk_name = preg_replace('/\s+/','_',$trunk_name);
			updateStatus($debug, $db, $trunk_name, $status);
			continue;
		}
	}
}

?>
