It will be recalled (see blog article dated June 25, 2023) that I fished for people to join me in an open-source project. The idea was to set up some PHP script that would run periodically, interrogating an API at the VOIP.MS company, querying the registration status of a long list of SIP trunks (what the company calls “subaccounts”). Now I have this working, in a sort of simple way.
Yes, just an hour ago I unplugged a VOIP phone, and 45 minutes later I received an email telling me that it had gotten unplugged. It means that my spiffy new SIP trunk monitor is working.
Here’s the PHP code:
<?php
$to = “<email-address>“;
$headers = “From:<email-address>” . “\r\n”;
$handle = fopen(“<linux-file-path>/sip-trunks.txt”, “r”);
if ($handle) {
while (($line = fgets($handle)) !== false) {
$pieces = explode(” “, $line);
$user = $pieces[4];
$pass = $pieces[2];
$account = $pieces[0];
$postfields = array(
‘api_username’ => $user,
‘api_password’ => $pass,
‘method’ => ‘getRegistrationStatus’,
‘account’ => $account
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_URL, “https://voip.ms/api/v1/rest.php”);
$result = curl_exec($ch);
curl_close($ch);
$data = json_decode($result, true);
if ($data[‘registered’] != “yes”) {
$subject = $pieces[1] . ” is down”;
$message = $pieces[1] . ” is down.”;
mail($to, $subject, $message, $headers);
}
;
}
fclose($handle);
}
?>
In this case the code is running on a Synology box, so most of the bowels of Linux are kept out of my view. I had to click around a bit to find out the detailed Linux file path for the file that contains the PHP script. (You go into the File Station and find the PHP script and right-click on it to see its properties, and the “location” will be revealed.) And then there is the place in this PHP script where it needs to open a file that contains 22 lines, each of which spells out a single SIP trunk to check the status of. And that file (“sip-trunks.txt”) has its own hard-to-find detailed Linux file path. In ordinary Linux I would be setting up a “cron job” to make the PHP script run periodically. In Synology this is a “scheduled task”. I chose to make it run every fifteen minutes. The script takes about fifteen seconds to run, and it checks about two dozen SIP trunks.
When I first tried this “scheduled task” in the Synology box, I would occasionally be scolded with this message:
Task Scheduler skipped a scheduled task because the task is already running.
What would then happen is that the task would keep running in perpetuity, meaning that I would cease to receive notifications. So now, in the Synology task scheduler, the Linux command line I use is:
php -d max_execution_time=120 /<linux-file-path>/sip-trunks.php
The point of the “-d” option is to bring in what might have been a line in a php.ini file, namely the setting “max_execution_time”. This kills the scheduled task if it has the bad luck to try to run longer than 120 seconds.
On the Synology box in question, I had to think through that I would have to install PHP on that box. Not only that, I had to think through that I had to configure the PHP, as invoked in the “web station”, to include Curl in the PHP.
And then there is the pesky problem of sending mail from PHP. With the first Synology box that I tried, I guess maybe it had an older version of the Synology operating system or something. It never did permit PHP to send email, even though test emails from the “Notifications” control panel came through just fine. I then repeated the experiment on a different and somewhat newer Synology box and although I do not know exactly why, on that box the PHP was indeed capable of sending emails.
The alert reader will ask what is the syntax of a line in the sip-trunks.txt file? Here is a generic line from that file:
<six-digit VOIP.MS account number>_<subaccount ID> <human-readable description of the SIP trunk> <API password> 88 <user ID at VOIP.MS>
The API at VOIP.MS has some coding oddity that it handles the user ID differently depending on whether it does or does not have a hyphen in it. There is a field in the API where you could, optionally, limit which IP addresses are permitted to query the API. That field may be left blank if the user ID does not contain any hyphens. But that field needs to contain “*.*.*.*” if the user ID happens to contain a hyphen. This burned up at least an hour of my time to work out.
The PHP code quoted above is, of course, very crude. It maintains no history, no event logging. So once I unplug a test phone, then every fifteen minutes another email will arrive telling me, as if for the first time, that the associated SIP trunk has lost its registration.
Alert coders in PHP will see that my PHP code is sloppy and fragile. I fail to check for returned errors from the various functions and procedure calls. I fail to check boundary conditions in arrays or other “countable” things. I fail to do any logging. I fail to syntax-check anything that arrives from the sip-trunks.txt file. If there were a space in the human-readable text of a line in the sip-trunks.txt file, it would make things crash (because I lazily use “explode”).
Oh and what about that “88” in the sample line from the sip-trunks.text file? What is that all about?