SIP через WebRTC на продакшне. Как мы к этому шли и какие проблемы решали

от автора

Доброго времени суток всем!

Я уже писал о своем опыте работы с WebRTC тут, но учитывая то, что в последнее время всё больше статей на эту тему появляется на хабре и то, что я давно хотел написать о том, как мы добились стабильной работы SIP телефонии через WebRTC на продашне, я решил написать через что мы прошли.

А прошли мы через многое: боль, панику, истерики, кучу матов и пожелания добра мейнтейнерам.
Сейчас же это всё в прошлом. Мы избавились от всех костылей, которые мы делали, и сделали так, чтобы операторы звонили и всё работало стабильно.
В статье, я как можно подробнее описал все проблемы, с которыми мы сталкивались, используя как можно меньше кода и конфигов.

Кому интересно, прошу под кат.

Предыстория:

Мы писали софт для нашего колцентра и у нас была возможность делать его так, чтобы не заморачиватся насчет кроссбраузерности.

На первоначальном этапе мы выбрали:

  • SIPml5 — как фронтенд либу
  • Asterisk — как бекенд
  • Google Chrome — как браузер. где всё это должно работать.

За весь путь мы использовали:

  • Asterisk и SIPml
  • Asterisk + Webrtc2sip и SIPml
  • Freeswitch + SIPml
  • Freeswitch + JSSIP

Не много о софтах:

  • Asterisk — всем известный soft-switch. Делается умельцами из Digium
  • Freeswitch — Soft-switch. Oдин из конкурентов Asterisk
  • SIPml5 — позицианируют себя как первый HTML5 SIP клиент. Javascript либа для работы с SIP.
  • JSSIP — легковесная Javascript либа для работы с SIP.
  • WebRTC2SIP — SIP и медиа гейтвей

asterisk + sipml

Начало пути. Нам надо было добится рабочей схемы и позвонить с браузера себе на мобильный.
Asterisk патчили и компиляли по этому мануалу
После того, как мы этого добились, мы начали тестировать.

В процессе тестирования мы обнаружили:

  1. «Белый шум» при звонке
  2. Тишина до 10 секунд при входящем звонке.
  3. Входящий звонок скидывал исходящий.

1. «Белый шум» был исправлен с помощью этого патча
2. Проблему со скидыванием звонка удалось решить, с помощью настройки пользователя на Asterisk. Был выставлен лимит 1 звонок на пользователя.
3. Проблему с 10 секундной тишиной решили исправить, обновив Asterisk до версии 1.6.

И вот мы уже на 1.6 астериске. После беглого тестирования стало понятно:

  • «Белого шума» нет
  • Нативная поддержка вебсокетов

Но появились следующие проблемы:

  1. Астериск падает при входящем звонке на определении RTP
  2. Тишина до 10 секунд осталась.

Проблему с тишиной удалось решить тем, что мы отказались от STUN в SIPml5. Ситуация стала лучше, но не исчезла полностью.
Решили попробовать WebRTC2SIP, как советовали мейнтейнеры SIPml5.

asterisk + webrtc2sip + sipml

На этом этапе у нас следующая ситуация:

  • Нет старых багов
  • Asterisk не падает
  • Тишина исчезла.

НО! Появилась проблема в том, что WebRTC2SIP не готов для продакшна. Он постоянно падал с разной периодичностью.
Судя по багрепорту в треккере о проблеме знали уже полгода, когда мы стали его использовать. Поняв, что от мейнтейнеров ничего не добится, стали проблему решать сами.

// А тем временем проект уже в продакшне.

Потратив неделю и так не решив проблему, сделали рестартер webrtc2sip и стали смотреть в сторону Freeswitch.

freeswitch + sipml

В сторону Freeswitch я смотрел еще тогда, когда вышла Бета версия 1.4 с поддержкой WebRTC.

На этом этапе стало понятно, что ни от Asterisk, ни от Doubango Telecom помощи ждать не стоит и нужно как-то решать проблему самим.

На начальных этапах работы с Freeswitch очень выносят мозг xml конфиги, но когда привыкаешь к ним, то жить без них не можешь.
После того, как мы добились от него работы в условиях, приближенных к продакшну, протестировали его, и поняв, что багов нет, стали тестировать дальше на продакшне, сохранив возможность перейти обратно на связку Asterisk + WebRTC2SIP

После миграции проблемы со стороны софтсвитча исчезли. Появились проблемы со стороны SIPml:

  • Если позвонить и скинуть трубку, то sipml будет думать, что ему также звонят и будет пробовать взять уже мертвый звонок.
  • Звонок длился не больше 2х минут.

Сделали несколько костылей для того, чтобы эти проблемы нам не мешали и решили перейти на JSSIP. О JSSIP знали уже около месяца. А еще тут было много ненависти к Doubango и их продуктам и огромное желание избавится от их продуктов.

Проверив все на tryit.jssip.net и поняв, что проблем нет, через три дня, после миграции на JSSIP, у нас SIP стал работать стабильно и без багов.

Резюме

Вот такая история получилась. А теперь мое личное мнение по каждому софту.

SIPml

Плюсы:

  • Поддерживает трансфер

Минусы:

  • Очень огромная. Минифицированный js файл весит > 1 Mb
  • Нет полной документации. Много чего приходилось выискивать по интернетам.
  • Больше заточена под WebRTC2sip
  • Много кода
Пример подключения к серверу

// Взято из документации          SIPml.init(                     function(e){                         var stack =  new SIPml.Stack({realm: 'example.org', impi: 'bob', impu: 'sip:bob@example.org', password: 'mysecret',                             events_listener: { events: 'started', listener: function(e){                                         var callSession = stack.newSession('call-audiovideo', {                                                 video_local: document.getElementById('video-local'),                                                 video_remote: document.getElementById('video-remote'),                                                 audio_remote: document.getElementById('audio-remote')                                             });                                         callSession.call('alice');                                     }                                  }                         });                         stack.start();                     }             ); 

Скрытый текст

// Взято из документации             var callSession;             var eventsListener = function(e){                 console.info('session event = ' + e.type);             }             var makeCall = function(){                 callSession = sipStack.newSession('call-audiovideo', {                     video_local: document.getElementById('video-local'),                     video_remote: document.getElementById('video-remote'),                     audio_remote: document.getElementById('audio-remote'),                     events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events                 });                 callSession.call('johndoe');             }          

JSSIP

Плюсы:

  • Легковесная (~130kb)
  • Отличная документация на сайте разработчика
  • Отлично работает с Freeswitch(по идее и с Asterisk и другими, но тут я уже не проверял)
  • Отличное API

Минусов у либы я не заметил.

Скрытый текст

// Из документации var configuration = {   'ws_servers': 'ws://sip-ws.example.com',   'uri': 'sip:alice@example.com',   'password': 'superpassword' }; var coolPhone = new JsSIP.UA(configuration);  

Скрытый текст

// из документации var selfView =   document.getElementById('my-video'); var remoteView =  document.getElementById('peer-video');  // Register callbacks to desired call events var eventHandlers = {   'progress':   function(e){ /* Your code here */ },   'failed':     function(e){ /* Your code here */ },   'started':    function(e){     var rtcSession = e.sender;      // Attach local stream to selfView     if (rtcSession.getLocalStreams().length > 0) {       selfView.src = window.URL.createObjectURL(rtcSession.getLocalStreams()[0]);     }      // Attach remote stream to remoteView     if (rtcSession.getRemoteStreams().length > 0) {       remoteView.src = window.URL.createObjectURL(rtcSession.getRemoteStreams()[0]);     }   },   'ended':      function(e){ /* Your code here */ } };  var options = {   'eventHandlers': eventHandlers,   'extraHeaders': [ 'X-Foo: foo', 'X-Bar: bar' ],   'mediaConstraints': {'audio': true, 'video': true} };  coolPhone.call('sip:bob@example.com', options); 

Webrtc2sip

Плюсы:

  • Помог решить проблему с Asterisk

Минусы:

  • Не стабильный
  • Стабильность наладили спустя год.
Asterisk

Как я понял, умельцы в одном релизе чинят, в другом ломают.
На версии 1.7 SIP через WebRTC работать у меня перестал.

Хабраюзер Ovoshlook отлично и подробно описал проблему:

Умельцы уже пропатчили. сейчас всеобщая и всепоглащающая проблема в другом- когда астериск делает бриджинг он посылает инвайт с транспортом AVP, и если вызываемый абонент сидит на вебфоне — он соответственно ожидает транспорт AVPF и шифрование. Как следствие при звонке вызываемый будет отвечать 603 ошибкой c комментарием failed to get local sdp.
В общем и целом — при исходящх астериск не следит за тем с какого устройства на нем сидит клиент. Как вариант можно проксировать и преобразовывать через openSIPS или Kamailio, но это уже совсем другая тема.

В итоге всё это надоело и мы выбрали Freeswitch как soft-switch

Freeswitch

Плюсы:

  • Работает
  • Активно разрабатывается
  • Ничего не ломается в новых релизах

Минусы:

  • Нет возможности сделать подобный колцентр, как в asterisk бабой-роботом

Итог

SIP стал работать стабильно. Операторы счастливы. Текущая связка Freeswitch+JSSIP обрабатывает ~10k звонков в сутки и до 15k в часы-пик.

PS

Кому интересно могу написать о том, как мы настраивали Freeswitch с интеграцией с MySQL, кол-центром, записью звонков и делали его отказоустойчивым.

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


Комментарии

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

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