Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Материал статьи взят с моего дзен-канала.
Структура RTP-пакета
В прошлой статье мы с помощью TShark выполнили захват RTP-пакетов, которыми обменивались наши приемник и передатчик. Ну а в этой мы раскрасим элементы пакета в разные цвета и поговорим об их назначении.
Взглянем на тот же пакет, но уже с подкрашенными полями и с поясняющими надписями:
В нижней части листинга подкрашены байты, которые составляют RTP-пакет, а он в свою очередь является полезной нагрузкой UDP-пакета (его заголовок обведен черной линией). Цветными фонами обозначены байты RTP-заголовка, а зеленым цветом выделен блок данных, который содержит полезную нагрузку RTP-пакета. Данные там представлены в шестнадцатиричном формате. В нашем случае это звуковой сигнал сжатый по u-закону (мю-закону), т.е. один отсчет имеет размер 1 байт. Поскольку мы использовали сэмплингрейт, установленный по умолчанию (8000 Гц), то при частоте пакетов 50 Гц каждый RTP-пакет должен содержать 160 байт полезной нагрузки. Это мы и увидим, посчитав байты в зеленой области, их должно оказаться 10 строчек.
По стандарту, количество данных в полезной нагрузке должно быть кратно четырем, или иными словами должно содержать целое количество четырехбайтных слов. Если случится так, что ваша полезная нагрузка не будет соответствовать этому правилу, то в конце полезной нагрузки нужно добавить байты с нулевыми значениями и установить бит Padding (Дополнение). Этот бит расположен в первом байте RTP-заголовка, он подкрашен бирюзовым цветом. Обратите внимание, что все байты полезно нагрузки имеют значение 0xFF — так выглядит тишина в формате u-law.
Заголовок RTP-пакета состоит из 12 обязательных байтов, но в двух случаях он может быть длиннее:
Когда пакет несет звуковой сигнал полученный смешиванием сигналов от нескольких источников (RTP-потоков), то после первых 12 байт заголовка располагается таблица со списком идентификаторов источников, полезные нагрузки которых были использованы для создания полезной нагрузки этого пакета. При этом в младших четырех битах первого байта заголовка (поле Contributing source identifiers count) указывается количество источников. Размер поля составляет 4 бита, соответственно таблица может содержать до 15 идентификаторов источников. Каждый из которых занимает 4 байта. Эта таблица используется при организации конференц-связи.
Когда заголовок имеет расширение. В этом случае в первом байте заголовка устанавливается бит X. В расширенном заголовке, после таблицы участников ( если они есть), располагается заголовок расширения размером в одно слово, а вслед за ним слова расширения. Расширение это набор набор байтов которые вы можете использовать для того чтобы передавать дополнительные данные. Стандарт не оговаривает формат этих данных — он может быть любым. Например это могут быть какие-то дополнительные настройки для устройства, которое получает RTP-пакеты. Для некоторых применений, тем не менее разработаны стандарты расширенного заголовка. Так сделано например для средств связи в стандарте ED-137 ( Interoperability Standards for VoIP ATM Components ).
Теперь рассмотрим поля заголовка более детально. Ниже изображена каноническая картинка со структурой RTP-заголовка, которую я тоже не удержался и раскрасил в те же цвета.
VER — номер версии протокола (текущая версия 2);
P — флаг, который устанавливается в случаях, когда RTP-пакет дополняется пустыми байтами на конце;
X — флаг того, что заголовок расширенный;
CC — содержит количество CSRC-идентификаторов, следующих за постоянным заголовком (после слов 1..3), на рисунке таблица не показана;
M — маркер начала кадра или наличия речи в канале (если используется детектор пауз в речи). Если приемник не содержит детектор пауз в речи, то этот бит должен быть установлен постоянно;
PTYPE — указывает формат полезной нагрузки;
Sequence number — номер пакета, используется для восстановления порядка воспроизведения пакетов, так как реальная ситуация когда пакеты могут достигнуть приемника не в том порядке в котором их отправили. Начальное значение должно быть случайным, это делается для того, чтобы если применяется шифрование RTP-потока затруднить его взлом. Также это поле позволяет обнаруживать пропуски пакетов;
Timestamp — метка времени. Время измеряется в выборках сигнала, т.е. если пакет содержит 160 выборок, то метка времени следующего пакета будет больше на 160. Начальное значение временной метки должно быть случайным;
SSRC — идентификатор источника пакета, он должен быть уникальным. Его лучше генерировать случайным образом перед запуском RTP-потока.
Если вы будете разрабатывать свой передатчик или приемник RTP-пакетов, вам придется не раз рассматривать ваши пакеты, чтобы чтобы повысить продуктивность я вам рекомендую освоить использование фильтрации пакетов в TShark, она позволяет захватывать только те пакеты которые представляют интерес для вас. В условиях, когда в сети работают десятки RTP-устройств это очень ценно. В командной строке TShark параметры фильтрации задаются опцией "-f". Мы использовали эту опцию когда хотели захватить пакеты с порта 8010:
-f "udp port 8010"
Параметры фильтрации по своей сути это набор критериев которым должен соответствовать "отлавливаемый" пакет. Условие может проверять адрес, порт, значение определенного байта в пакете. Условия можно объединять логическими операциями "И", "ИЛИ" и т.п. Очень мощный инструмент.
Если вы хотите просмотреть динамику изменения полей в пакетах, вам потребуется продублировать вывод TShark в файл, как это было показано в прошлой статье, с помощью передачи вывода TShark на вход tee. Далее открыв лог-файл с помощью less, vim или другим инструментом, способным быстро работать с огромными текстовыми файлами и выполнять поиск строк, вы сможете выяснить все нюансы поведения полей пакетов в RTP-потоке.
Если вам потребуется прослушать сигнал передаваемый RTP-потоком, то нужно воспользоваться версией TShark c визуальным интерфейсом Wireshark. Путем несложных манипуляций мышью там можно прослушать, увидеть осциллограмму сигнала. Но при одном условии — если он будет закодирован в формате u-law или a-low.
В следующей статье мы сделаем с вами дуплексное переговорное устройство. Запаситесь парой гарнитур и одним собеседником.