При работе с SIP-телефонией достаточно часто можно встретить проблему отсутствия слышимости. Ошибка может возникнуть как на сети, так и на стороне SIP-устройства или приложения.
Хотелось бы поделиться сбоем, вероятность воспроизведения которого крайне мала - настолько, что техподдержке проще будет сослаться на ошибку из-за космических лучей: в ТП одного крупного оператора SIP-телефонии за 3 года зафиксировано 6 обращений, в которых такая проблема зафиксирована (из ~300.000 всего - 0.002%).
Данные для диагностики
Обращается абонент с примером звонка, в котором он не слышал другого собеседника.
Известно, что проблем на оконечном оборудовании с трубкой/гарнитурой/микрофоном нет.
Звук и пишется, и воспроизводится.
Имеется дамп SIP-звонка:
По протоколу SIP звонок успешно установлен (INVITE - 200 OK - ACK), пошёл нормальный обмен RTP-пакетами с двух сторон:
Наличие с одной стороны двух RTP дорожек нарушением не является - так, например, одна дорожка может быть мелодией ожидания от АТС, а потом уже голос абонента.
Потери и задержки на сети в норме (менее 5% и не более 150 мс):
С джиттером тоже всё хорошо. Максимальные значения нигде не зашкаливают:
Согласование кодеков прошло успешно - выбран PCMA (g711a).
Ptime у абонентов также совпадает - 20 мс.
При просмотре RTP-дорожек видно, что они непустые (идут колебания), но опять смущает разрыв со стороны одного абонента на 2 дорожки:
Как указано ранее - это частое явление и само по себе ошибкой не является.
Здесь вышло скорее наоборот - абонент B (с черной и коричневой дорожкой) не слышал абонента A (с единой синей). Хотя по идее, в его сторону отправка звука шла без разрыва.
На данном этапе мы проверили практически все параметры, которые требовали проверки при проблемах с качеством связи или отсутствием слышимости - кроме SSRC.
Смена SSRC
Что такое SSRC?
Synchronization source (SSRC): The source of a stream of RTP packets, identified by a 32-bit numeric SSRC identifier carried in the RTP header so as not to be dependent upon the network address. (RFC 3550 - стр. 10)
Проще говоря, SSRC - это идентификатор источника потока RTP:
По RFC 3550 и RFC 8108 SSRC менять можно. Несколько SSRC может использоваться при использовании абонентом нескольких типов мультимедиа (аудио + видео), нескольких устройств захвата голоса и т.д.
Один из авторов RFC 8108 предоставил комментарий:
Да, SSRC может измениться. Кроме того, вы можете увидеть несколько SSRC в сеансе (одноадресный сеанс не ограничивается одним SSRC от каждого участника или даже двумя участниками, поскольку один из них может быть транслятором или микшером RTP)
// перевод автора
В нашем случае первая дорожка имеет SSRC от IVR со стороны АТС, а вторая - от устройства абонента B.
Дополнительный параметр - CNAME
В ходе разбора вопроса удалось обнаружить, что помимо SSRC (о котором в принципе есть информация) RTCP содержит ещё один идентификатор для RTP - каноническое имя или CNAME (стр. 20 RFC 3550).
Так как идентификатор SSRC может измениться, получателям требуется CNAME для отслеживания каждого участника.
Каждый составной пакет RTCP должен (MUST) включать CNAME, так как он остается постоянным (стр. 46 RFC 3550).
Проверим, как абонент B с двумя дорожками и проблемой слышимости указывал данный параметр:
Как видим, CNAME не указан - нет текста с ним, а длина элемента 0 бит.
То есть, абонент B нарушает обязательные требования RFC 3550 и не указывает CNAME. В результате получаем сбой работы телефонии.
Проверка от обратного
Попробуем перепроверить свой вывод - действительно ли проблема не в разных SSRC / разрыве дорожек, а в отсутствии CNAME?
Вот пример звонка, в котором также разные SSRC, но CNAME указан - в нем со слышимостью полный порядок:
Более того, это пример звонка от того же самого абонента, но спустя некоторое время.
В чем отличие? - версия сервера АТС на его стороне обновилась (нестандартная АТС по типу известных Asterisk и т.д.). Вероятнее всего предыдущий релиз был с багом, т.к. до этого данный абонент длительное время успешно общался.
То есть, подтверждаем вывод, что проблема на АТС абонента B, не указавшей CNAME.
Выводы
Точной информации о том, как именно повел себя сервер абонента B при 2х SSRC без CNAME не имеется, но можно предположить, что поток от абонента A на его АТС или за ней некорректно маршрутизировался либо это было отражением иного системного сбоя.
Однако сам по себе факт нарушения обязательного пункта RFC в такой ситуации дает основания указать на необходимость глубокой проверки именно на стороне АТС абонента B.
Информация о таком параметре RTCP как CNAME встречается не то, чтобы часто, а тем более о возможных сбоях с ним.
Комментарии (10)
402d
31.05.2024 10:38+1Ну и зачем, я читал этот RFC ? Я ведь не связан с RTP протоколами.
Но даже беглого просмотра хватило, чтобы понять UUID в качестве CNAME тоже не айс.
datacompboy
Строго говоря, CNAME указан -- пустая строка. Так как в звонке два абонента, у второго непустая строка, то все требования соблюдены -- у каждого есть CNAME и они уникальны для каждого абонента.
xReaper
Не согласен с вами, если есть поле а значения нет то не указан, с такой логикой можно сказать что поле Connexion information IP4 "Пусто" должно работать.
datacompboy
Должно работать в каком смысле?
То есть CNAME необходим для уникального идентифицирования абонента в случае смены SSRC или наличия множества стримов.
Да, CNAME обязан быть передан -- и он передан, в пункте 6.5.1 я не вижу ничего, что делало бы пустую строку невалидной.
xReaper
Вы же сами написали про уникальный идентификатор, или для вас пустое поле это уникально ?
datacompboy
Если пустое поле только у одного абонента в разговоре -- да, "" -- уникально. Так же как уникально "вася" или "пыопрырц8процр".
xReaper
Конечно "Если" А Если нет ? Или мы будем спорить что уникальнее пустое поле или рандом ай ди ?
datacompboy
https://xkcd.com/221/
mrgervant Автор
Интересное замечание - не думал в таком ключе! К сожалению, информации о поведении АТС на стороне того абонента нет. Можно предполагать, что сам сервер по внутренней логике всё же ожидал получить текст CNAME, раз быстро вышло исправление его версии.
datacompboy
Я уверен, что это был баг на той стороне.
Однако это не отменяет того факта, что поведение вашей стороны тоже не совсем корректно: тут либо реакция должна быть такой же как на отсутствие тега CNAME вообще, скорее всего -- отказ в установлении соединения -- либо принять, и использовать его как есть -- то есть пустое значение это всё же значение.
Вы провели отличное глубокое расследование и нашли очень редкий случай, который обычно поймать можно только с помощью удачи (и/или фаззинга), теперь стоит сделать вывод и принять решение как реагировать на него с вашей стороны. :)
Чего точно не стоит делать -- так это хоронить проблему и забить.