- PVSM.RU - https://www.pvsm.ru -

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

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

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

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

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

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

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

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

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

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

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

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

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

asterisk + sipml

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

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

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

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

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

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

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

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

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

asterisk + webrtc2sip + sipml

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

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

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

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

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

freeswitch + sipml

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

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

На начальных этапах работы с Freeswitch очень выносят мозг [10] 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 [11] отлично и подробно описал проблему:

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

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

Freeswitch

Плюсы:

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

Минусы:

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

Итог

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

PS

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

Автор: Gen1us2k

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/telefoniya/61560

Ссылки в тексте:

[1] тут: http://habrahabr.ru/post/203568/

[2] Asterisk: http://www.asterisk.org/

[3] Freeswitch: http://freeswitch.org/

[4] SIPml5: http://www.sipml5.org/

[5] JSSIP: http://jssip.net/

[6] WebRTC2SIP: http://webrtc2sip.org/

[7] этому мануалу: https://code.google.com/p/sipml5/wiki/Asterisk

[8] этого: https://issues.asterisk.org/jira/secure/attachment/46844/whitenoise_fix.diff

[9] багрепорту: https://code.google.com/p/webrtc2sip/issues/detail?id=122

[10] мозг: http://www.braintools.ru

[11] Ovoshlook: http://habrahabr.ru/users/ovoshlook/

[12] Источник: http://habrahabr.ru/post/225239/