📜 ⬆️ ⬇️

Check the availability of the SIP provider

In this article I want to share one interesting way to check the availability of a sip provider or other device, especially when it’s not possible to verify icmp requests for any reason, and is based on OPTIONS requests for SIP. Who are interested in this topic please under cat. And so, the SIP protocol, which is described in RFC 3261, has a wonderful type of OPTIONS request, this type of request is used to verify the compatibility of the parties, it allows the client to get information about what methods the remote side supports, and most importantly, there is no need to make a call remote side (there is no need to send an INVITE request). Example OPTIONS request from RFC:
 OPTIONS sip: carol@chicago.com SIP / 2.0
       Via: SIP / 2.0 / UDP pc33.atlanta.com; branch = z9hG4bKhjhs8ass877
       Max-Forwards: 70
       To: <sip: carol@chicago.com>
       From: Alice <sip: alice@atlanta.com>; tag = 1928301774
       Call ID: a84b4c76e66710
       CSeq: 63104 OPTIONS
       Contact: <sip: alice@pc33.atlanta.com>
       Accept: application / sdp
       Content-Length: 0
The answer to such a request should be the same as if we sent an INVITE request, for example, it can be 200 (OK), meaning that the remote party is ready to accept the call. Let's get down to the practical part, it comes down to what we need to prepare the ip package with relevant data and send it to the remote side and get an answer to it. To do this, we can write a simple script, for example, in Perl:
 #! / usr / bin / perl
 use IO :: Socket;
 use POSIX 'strftime';

 sub SipPing {
         my ($ msg, $ remotehost, $ callid, $ socket, $ date, $ branch, $ localip, $ dest);
         $ remotehost = shift;
         $ localip = shift;
         $ socket = IO :: Socket :: INET-> new (
                 PeerAddr => $ remotehost,
                 PeerPort => 5060,
                 LocalPort => 5060,
                 LocalAddr => $ localip,
                 Reuse => 1, 
                 Proto => 'udp',
         );
         $ callid. = ('0' .. '9', "a" .. "f") [int (rand (16))] for 1 .. 32;
         $ date = strftime ('% a,% e% B% Y% I:% M:% S% Z', localtime ());
         $ branch = "z9hG4bk".  time ();
         my $ packet = qq (
             OPTIONS sip: $ remotehost SIP / 2.0
                Via: SIP / 2.0 / UDP $ localip: 5060; branch = z9hG4bK39aaa111; rport
                Max-Forwards: 70
                From: "UA" <sip: ua \ @ $ localip>; tag = as54192a85
                To: <sip: $ remotehost>
                Contact: <sip: asterisk \ @ $ localip: 5060>
                Call ID: 7706430b46622c057aeaa5ec057a0b59 \ @ $ localip: 5060
                CSeq: 102 OPTIONS
                User-Agent: UA
                Date: Wed, 21 Dec 2013 00:00:01 GMT
                Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
                Supported: replaces, timer
                Content-Length: 0
          );
         print $ socket $ packet;
         eval {
                 local $ SIG {ALRM} = sub {die};
                 alarm 1;
                 my $ sock_addr = recv ($ socket, $ msg, 190,0);
                 alarm 0;
                 one;
         } or die "Failed";
         if ($ msg) {
                 print "Response: $ msg \ n";
         } else {
                 print "Failed";
         }
         close ($ socket);
 }

 $ remoteHost = '192.168.0.3';
 $ localIp = '192.168.0.2';
 & SipPing ($ remoteHost, $ localIp);

With the help of such a simple script, you can check the availability of the SIP agent, without the need for registration or a call. It should be noted that some providers allow receiving OPTIONS requests only from port 5060 to port 5060, for this we specify the local port, and if the port is busy, for example, Asterisk, then the Reuse => 1 parameter is useful. That's all.

')

Source: https://habr.com/ru/post/212401/


All Articles