Проверяем доступность SIP провайдера

от автора

В это статье хочу поделиться одним интересным на мой взгляд способом проверки доступности sip провайдера, или другого устройства, особенно он актуален когда по какой-либо причине нельзя проверить сторону icmp запросами, и основывается на OPTIONS запросах протокола SIP. Кого заинтересовала данная тема прошу под кат.И так, протокол SIP, который описан в RFC 3261, имеет замечательный тип запроса OPTIONS, данный тип запроса используется для проверки совместимости сторон, он позволяет клиенту получить информацию о том, какие методы поддерживает удаленная сторона, и что самое главное, нет необходимости совершать вызов удаленной стороны(нет необходимости в отправке INVITE запроса). Пример OPTIONS запроса из 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 

Ответ на такой запрос должен быть таким же, как если мы отправили запрос INVITE, например это может быть ответ 200(OK), означающий что удаленная сторона готова принять звонок.Приступим к практической части, она сводиться к тому, что нам необходимо подготовить ip пакет с соответствующими данными и отправить его удаленной стороне и получить на него ответ. Для этого можем написать простой скрипт, например на 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 1;                 1;         } or "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);  

С помощью такого нехитрого скрипта можно проверить доступность SIP агента, без необходимости регистрации или звонка. Стоит отметить, что некоторые провайдеры разрешают получение OPTIONS запросов только с порта 5060 на порт 5060, для этого указываем локальный порт, а в случае если порт занят, например Asterisk’ом, то пригодиться параметр Reuse => 1.На этом всё.

ссылка на оригинал статьи http://habrahabr.ru/post/212401/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *