Сигнализация

Сигнализация #

Что такое сигнализация WebRTC? #

Когда вы создаете агента WebRTC, он ничего не знает о другом пире. У него нет представления, с кем он будет подключаться или что будет отправляться! Сигнализация - это начальная загрузка, которая делает вызов возможным. После обмена этими значениями WebRTC-агенты могут напрямую общаться друг с другом.

Сигнальные сообщения - это просто текст. WebRTC-агенты не заботятся о том, как они передаются. Обычно они передаются через Websockets, но это не является обязательным требованием.

Как работает сигнализация WebRTC? #

WebRTC использует существующий протокол, называемый Session Description Protocol. Через этот протокол два WebRTC-агента будут обмениваться всем состоянием, необходимым для установления соединения. Сам протокол прост для чтения и понимания. Сложность заключается в понимании всех значений, которые WebRTC заполняет.

Этот протокол не специфичен для WebRTC. Мы сначала изучим Session Description Protocol, даже не говоря о WebRTC. WebRTC использует только подмножество протокола, поэтому мы рассмотрим только то, что нам нужно. После того, как мы поймем протокол, мы перейдем к его практическому использованию в WebRTC.

Что такое Session Description Protocol (SDP)? #

Session Description Protocol определен в RFC 8866. Это протокол “ключ/значение” с новой строкой после каждого значения. Он будет похож на INI-файл. Описание сессии содержит ноль или более описаний медиа. Мысленно вы можете представить его как описание сессии, содержащее массив описаний медиа.

Описание медиа обычно соответствует одному потоку медиа. Так что если бы вы хотели описать вызов с тремя видеопотоками и двумя аудиотреками, у вас было бы пять описаний медиа.

Как читать SDP #

Каждая строка в описании сессии будет начинаться с одного символа - это ваш ключ. За ним следует знак равенства. Все после знака равенства - это значение. После завершения значения будет новая строка.

Session Description Protocol определяет все допустимые ключи. Вы можете использовать только буквы для ключей, как определено в протоколе. У этих ключей есть значимый смысл, который будет объяснен позже.

Возьмем этот фрагмент описания сессии:

a=my-sdp-value
a=second-value

У вас две строки. Каждая с ключом a. Первая строка имеет значение my-sdp-value, вторая строка имеет значение second-value.

WebRTC использует только некоторые ключи SDP #

Не все значения ключей, определенные Session Description Protocol, используются WebRTC. Важны только ключи, используемые в JavaScript Session Establishment Protocol (JSEP), определенном в RFC 8829. Следующие семь ключей - единственные, которые вам нужно понять прямо сейчас:

  • v - Версия, должна быть равна 0.
  • o - Происхождение, содержит уникальный ID, полезный для повторных переговоров.
  • s - Имя сессии, должно быть равно -.
  • t - Время, должно быть равно 0 0.
  • m - Описание медиа (m=<media> <port> <proto> <fmt> ...), описано подробнее ниже.
  • a - Атрибут, текстовое поле. Это самая распространенная строка в WebRTC.
  • c - Данные о подключении, должны быть равны IN IP4 0.0.0.0.

Описания медиа в описании сессии #

Описание сессии может содержать неограниченное количество описаний медиа.

Определение описания медиа содержит список форматов. Эти форматы сопоставляются с RTP Payload Types. Сам кодек затем определяется атрибутом со значением rtpmap в описании медиа. Важность RTP и RTP Payload Types обсуждается позже в главе о медиа. Каждое описание медиа может содержать неограниченное количество атрибутов.

Возьмем этот фрагмент описания сессии в качестве примера:

v=0
m=audio 4000 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 4000 RTP/AVP 96
a=rtpmap:96 VP8/90000
a=my-sdp-value

У вас два описания медиа: одно типа audio с fmt 111 и одно типа video с форматом 96. Первое описание медиа имеет только один атрибут. Этот атрибут сопоставляет Payload Type 111 с Opus. Второе описание медиа имеет два атрибута. Первый атрибут сопоставляет Payload Type 96 с VP8, а второй атрибут просто my-sdp-value.

Полный пример #

Следующий пример объединяет все концепции, о которых мы говорили. Это все функции Session Description Protocol, которые использует WebRTC. Если вы можете прочитать это, вы можете прочитать любое WebRTC-описание сессии!

v=0
o=- 0 0 IN IP4 127.0.0.1
s=-
c=IN IP4 127.0.0.1
t=0 0
m=audio 4000 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 4002 RTP/AVP 96
a=rtpmap:96 VP8/90000
  • v, o, s, c, t определены, но не влияют на сеанс WebRTC.
  • У вас два описания медиа. Одно типа audio и одно типа video.
  • У каждого есть один атрибут. Этот атрибут настраивает детали RTP-конвейера, который обсуждается в главе “Медиа-коммуникация”.

Как Session Description Protocol и WebRTC работают вместе #

Следующий элемент головоломки - понимание как WebRTC использует Session Description Protocol.

Что такое Offers и Answers? #

WebRTC использует модель предложения/ответа. Это означает, что один WebRTC-агент делает “Предложение” для начала вызова, и другие WebRTC-агенты “Отвечают”, если они готовы принять предложенное.

Это дает отвечающему возможность отклонить неподдерживаемые кодеки в описаниях медиа. Так два пира могут понять, какие форматы они готовы обмениваться.

Трансиверы для отправки и получения #

Трансиверы - это концепция, специфичная для WebRTC, которую вы увидите в API. Она раскрывает “Описание медиа” в JavaScript API. Каждое описание медиа становится Трансивером. Каждый раз, когда вы создаете Трансивер, новое описание медиа добавляется в локальное описание сессии.

Каждое описание медиа в WebRTC будет иметь атрибут направления. Это позволяет WebRTC-агенту заявить “Я собираюсь отправить вам этот кодек, но я не готов принимать ничего взамен”. Есть четыре допустимых значения:

  • send
  • recv
  • sendrecv
  • inactive

SDP-значения, используемые WebRTC #

Это список некоторых распространенных атрибутов, которые вы увидите в описании сессии от WebRTC-агента. Многие из этих значений контролируют подсистемы, о которых мы еще не говорили.

group:BUNDLE #

Объединение - это акт передачи нескольких типов трафика по одному соединению. Некоторые реализации WebRTC используют выделенное соединение для каждого медиапотока. Объединение следует предпочитать.

fingerprint:sha-256 #

Это хеш сертификата, который пир использует для DTLS. После завершения DTLS-рукопожатия вы сравниваете его с фактическим сертификатом, чтобы подтвердить, что общаетесь с кем ожидаете.

setup: #

Это контролирует поведение DTLS-агента. Определяет, будет ли он работать как клиент или сервер после подключения ICE. Возможные значения:

  • setup:active - Работать как DTLS-клиент.
  • setup:passive - Работать как DTLS-сервер.
  • setup:actpass - Попросить другого WebRTC-агента выбрать.

mid #

Атрибут “mid” используется для идентификации медиапотоков в описании сессии.

ice-ufrag #

Это значение фрагмента пользователя для ICE-агента. Используется для аутентификации ICE-трафика.

ice-pwd #

Это пароль для ICE-агента. Используется для аутентификации ICE-трафика.

rtpmap #

Это значение используется для сопоставления определенного кодека с RTP Payload Type. Payload types не статичны, поэтому для каждого вызова отправляющий решает payload types для каждого кодека.

fmtp #

Определяет дополнительные значения для одного Payload Type. Это полезно для передачи определенного видеопрофиля или настроек кодировщика.

candidate #

Это ICE-кандидат, исходящий от ICE-агента. Это один из возможных адресов, на котором доступен WebRTC-агент. Они полностью объясняются в следующей главе.

ssrc #

Synchronization Source (SSRC) определяет один медиапоток.

label - это ID для этого отдельного потока. mslabel - это ID для контейнера, который может содержать несколько потоков внутри.

Пример описания сессии WebRTC #

Следующее - полное описание сессии, сгенерированное WebRTC-клиентом:

v=0
o=- 3546004397921447048 1596742744 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 0F:74:31:25:CB:A2:13:EC:28:6F:6D:2C:61:FF:5D:C2:BC:B9:DB:3D:98:14:8D:1A:BB:EA:33:0C:A4:60:A8:8E
a=group:BUNDLE 0 1
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=setup:active
a=mid:0
a=ice-ufrag:CsxzEWmoKpJyscFj
a=ice-pwd:mktpbhgREmjEwUFSIJyPINPUhgDqJlSd
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:350842737 cname:yvKPspsHcYcwGFTw
a=ssrc:350842737 msid:yvKPspsHcYcwGFTw DfQnKjQQuwceLFdV
a=ssrc:350842737 mslabel:yvKPspsHcYcwGFTw
a=ssrc:350842737 label:DfQnKjQQuwceLFdV
a=msid:yvKPspsHcYcwGFTw DfQnKjQQuwceLFdV
a=sendrecv
a=candidate:foundation 1 udp 2130706431 192.168.1.1 53165 typ host generation 0
a=candidate:foundation 2 udp 2130706431 192.168.1.1 53165 typ host generation 0
a=candidate:foundation 1 udp 1694498815 1.2.3.4 57336 typ srflx raddr 0.0.0.0 rport 57336 generation 0
a=candidate:foundation 2 udp 1694498815 1.2.3.4 57336 typ srflx raddr 0.0.0.0 rport 57336 generation 0
a=end-of-candidates
m=video 9 UDP/TLS/RTP/SAVPF 96
c=IN IP4 0.0.0.0
a=setup:active
a=mid:1
a=ice-ufrag:CsxzEWmoKpJyscFj
a=ice-pwd:mktpbhgREmjEwUFSIJyPINPUhgDqJlSd
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=ssrc:2180035812 cname:XHbOTNRFnLtesHwJ
a=ssrc:2180035812 msid:XHbOTNRFnLtesHwJ JgtwEhBWNEiOnhuW
a=ssrc:2180035812 mslabel:XHbOTNRFnLtesHwJ
a=ssrc:2180035812 label:JgtwEhBWNEiOnhuW
a=msid:XHbOTNRFnLtesHwJ JgtwEhBWNEiOnhuW
a=sendrecv

Вот что мы знаем из этого сообщения:

  • У нас два медиа-раздела: один аудио и один видео.
  • Оба они sendrecv трансиверы. Мы получаем два потока и можем отправить два обратно.
  • У нас есть ICE-кандидаты и детали аутентификации, поэтому мы можем попытаться подключиться.
  • У нас есть отпечаток сертификата, поэтому мы можем провести безопасный вызов.

Дополнительные темы #

В более поздних версиях этой книги также будут рассмотрены следующие темы:

  • Повторные переговоры
  • Симулкаст