Asterisk: processing registration events on a server using the example of interaction with the Multifon VoIP service

Hello, Habrahabr! In this article I want to talk about how you can solve the issue of automatically switching the mode of receiving calls in the Multiphone (gsm-to-gsm / gsm-to-sip) when registering a smartphone on the Asterisk server. Below we will explain why I needed it, what solution options were considered, and how it was eventually implemented. The following example was used on the basis of a home server running Debian Lenny along with Asterisk 1.6, but it will most likely work on other common Linux platforms.

Briefly on the background of the issue


Being a subscriber of Megafon, recently began to use their VoIP service. One of the features of the service is that in addition to making outgoing calls, you can receive incoming calls to a mobile number through a SIP client. I wanted to take this opportunity by setting up the connection of my smartphone to the Asterisk home server via SIP. I will not dwell on the registration procedure itself, connecting to the service and setting up the SIP account - this has already been written about enough. I wanted to do the following: when you connect your smartphone to the server, all incoming cellular calls begin to come through SIP; when disconnected from the server, the normal mode of receiving calls by the phone (gsm-to-gsm) should be restored.

What is needed to complete the task


To achieve this, it is necessary to fulfill at least two conditions:
1. “Multifon” should provide the ability to switch the mode of receiving cellular calls: receive to mobile, receive to a sip client. The service has such an opportunity, and it is implemented by sending a specific https request to the server (more about the request format can be found by clicking on the link indicated at the end of the article). The request can be executed from the console (for example, using curl or wget), which makes it possible to use it in scripts.
2. The server should “know” that a certain peer (smartphone) has registered on Asterisk, and when connecting / disconnecting, perform an https request. We will consider this question in more detail below.

In search of a solution


It is necessary to determine the moment when the smartphone will register on the server. Having studied Asterisk’s reaction to the client’s connection and the available means of informing about the event, I determined for myself 2 main solutions: to find out about the event through the AMI (Asterisk manager API) or to process through the external script a list of connected clients that Asterisk displays with the command “sip show peers. " The second option was closer to me, so I decided to stay on it. ( By the way, now I thought that there is still a third way - to parse the output of the file / var / log / asterisk / full for the presence of the lines “Registered SIP 'peername'” and “Unregistered SIP 'peername'.” Perhaps this would be even simpler, but I went the other way. If you know simpler options, tell me, I will listen to them with pleasure ).

Let's see what the server writes:

asterisk*CLI> sip show peers
Name/username              Host            Dyn Nat ACL Port     Status     
peer1/peer1                192.168.XXX.XXX  D          5060     Unmonitored 
peer2/peer2                (Unspecified)    D          5060     Unmonitored 
peer3/peer3                192.168.XXX.XXX  D          5060     Unmonitored 
multifon/7922XXXXXXX       193.201.229.35              5060     OK (34 ms) 
sipnet/sipnet		   212.53.40.40                5060     Unmonitored 
mywifipeer/mywifipeer      (Unspecified)    D          0        Unmonitored 
6 sip peers [Monitored: 1 online, 0 offline Unmonitored: 4 online, 1 offline]

In the column “Host” for disconnected clients we see the inscription (Unspecified), and for registered ones - IP-address. This data is enough to determine the registration status of the client. Thus, the task boiled down to writing a script that would query the server for the status of the necessary sip account (smartphone - mywifipeer), and if its registration status had changed, send an https request. To control the changes made, information about the event will be duplicated in jabber. Next, the script is placed in cron and executed every minute.

Since the script will work on demand, and not as a daemon, to determine that the connection status has changed, you must have information about how it was at the time of the previous launch. If this is not done, our script will DOS the megaphone server, sending him a request to set the GSM mode every time during the check, which is bad. Therefore, the first time the script calls, it will put information about the current status ($ peer_state_now) into an external file ($ peer_state_last_file), and all subsequent ones will read information from this file ($ peer_state_last) and check against the current status.

Curl was used to send the http request, sendxmpp ($ xmpp_bin and $ xmpp_jid) was used to notify the gabber. Before using the script, you must specify the login password corresponding to the Multifon-SIP registration record ($ multifon_login and $ multifon_password).

Asterisk_peer_check script



#!/bin/bash                                                                                                                     
#
# press F1 for help
if [ -z "$1" ]; then
    echo "Usage: $0 "
    exit 1
fi
# determining the future...
peer=$1
path="/var/spool/asterisk/tmp"
peer_state_last_file="$path/peer_state_$peer"
# Multifon account
multifon_login="7922XXXXXXX@multifon.ru"
multifon_password="mypassword"
# Jabber account for report
xmpp_jid="change_me@jabberserver.ru"
xmpp_bin="sendxmpp"
#getting actual peer state from asterisk
peer_state_now=`asterisk -rx "sip show peers" | grep -i $peer | awk '{print $2}'`;
#getting previous peer state from file
if [ -f "$peer_state_last_file" ]; 
    then
        peer_state_last=`cat $peer_state_last_file`
    else
        #first run
        peer_state_last=$peer_state_now
fi
#comparing actual peer status with previous
if [ "$peer_state_now" != "$peer_state_last" ]
    then
        #peer status changed
        if [ "$peer_state_now" = "(Unspecified)" ]
        then
            #GSM-2-GSM
            multifon_routing="0"
        else
            #GSM-2-SIP
            multifon_routing="1"
        fi
        #changing multifon status
        multifon_url="https://sm.megafon.ru/sm/client/routing/set?login=$multifon_login&password=$multifon_password&routing=$multifon_routing"
        curl --silent $multifon_url >/dev/null
        #jabber announce, if sendxmpp installed
        which $xmpp_bin >/dev/null || [ $? -eq 0 ] && echo "[`hostname`] Asterisk: Megafon incoming calls set to $multifon_routing" | $xmpp_bin -i $xmpp_jid
fi
#writing actual peer state in file
echo $peer_state_now > $peer_state_last_file
#

It remains to add the launch of the script in / etc / crontab

#
* *     * * *   root    /etc/cron/asterisk_peer_check mywifipeer
#

Done! Now you can check the health of the entire system. We connect the phone to the server and in a minute we get a confirmation message in jabber. We make a test call to the phone and make sure that everything works as it was intended.

References:


Multifon: http-request format, server responses and code processing

Also popular now: