Что, Зачем и Как #
Что такое WebRTC? #
WebRTC, сокращение от Web Real-Time Communication, это одновременно и API, и Протокол. Протокол WebRTC - это набор правил для двух агентов WebRTC для согласования двунаправленной безопасной связи в реальном времени. API WebRTC позволяет разработчикам использовать протокол WebRTC. API WebRTC определен только для JavaScript.
Похожие отношения можно провести между HTTP и Fetch API. WebRTC как протокол будет HTTP, а WebRTC как API будет Fetch API.
Протокол WebRTC доступен в других API и языках помимо JavaScript. Вы также можете найти серверы и специализированные инструменты для WebRTC. Все эти реализации используют протокол WebRTC, чтобы они могли взаимодействовать друг с другом.
Протокол WebRTC поддерживается в IETF в рабочей группе rtcweb. API WebRTC документирован в W3C как webrtc.
Почему я должен изучать WebRTC? #
Вот некоторые вещи, которые даст вам WebRTC:
- Открытый стандарт
- Множество реализаций
- Доступность в браузерах
- Обязательное шифрование
- Обход NAT
- Повторное использование существующих технологий
- Контроль перегрузки
- Задержка менее секунды
Этот список не исчерпывающий, а всего лишь пример некоторых вещей, которые вы можете оценить в процессе изучения. Не волнуйтесь, если вы пока не знаете всех этих терминов, эта книга научит вас им по мере прочтения.
Протокол WebRTC - это набор других технологий #
Протокол WebRTC - это огромная тема, которая потребовала бы целой книги для объяснения. Однако, для начала мы разделим его на четыре шага:
- Сигнализация
- Подключение
- Защита
- Коммуникация
Эти шаги последовательны, что означает, что предыдущий шаг должен быть на 100% успешным, прежде чем начнется следующий.
Любопытный факт о WebRTC заключается в том, что каждый шаг на самом деле состоит из многих других протоколов! Чтобы создать WebRTC, мы объединяем многие существующие технологии. В этом смысле, вы можете думать о WebRTC скорее как о комбинации и конфигурации хорошо понятных технологий, восходящих к началу 2000-х, чем как о совершенно новом процессе.
Каждому из этих шагов посвящена отдельная глава, но сначала полезно понять их на высоком уровне. Поскольку они зависят друг от друга, это поможет объяснить далее цель каждого из этих шагов.
Сигнализация: Как пиры находят друг друга в WebRTC #
Когда агент WebRTC начинает работу, он не знает, с кем будет общаться и о чем. Шаг Сигнализации решает эту проблему! Сигнализация используется для начальной загрузки вызова, позволяя двум независимым агентам WebRTC начать общение.
Сигнализация использует существующий текстовый протокол SDP (Session Description Protocol). Каждое SDP-сообщение состоит из пар “ключ-значение” и содержит список “медиа-секций”. SDP, который обмениваются два агента WebRTC, содержит такие детали как:
- IP-адреса и порты, на которых агент доступен (кандидаты).
- Количество аудио- и видеотреков, которые агент хочет отправить.
- Аудио- и видеокодеки, поддерживаемые каждым агентом.
- Значения, используемые при подключении (
uFrag
/uPwd
). - Значения, используемые при защите (отпечаток сертификата).
Очень важно отметить, что сигнализация обычно происходит “вне полосы”, что означает, что приложения обычно не используют сам WebRTC для обмена сигнальными сообщениями. Должен существовать другой канал связи между двумя сторонами перед началом подключения WebRTC. Тип используемого канала не является заботой WebRTC. Любая архитектура, подходящая для отправки сообщений, может передавать SDP между подключающимися пирами, и многие приложения просто используют свою существующую инфраструктуру (например, REST-эндпоинты, WebSocket-соединения или прокси-серверы аутентификации) для обмена SDP между соответствующими клиентами.
Подключение и обход NAT с помощью STUN/TURN #
После того, как два агента WebRTC обменялись SDP, у них есть достаточно информации для попытки подключения друг к другу. Для осуществления этого подключения WebRTC использует другую устоявшуюся технологию, называемую ICE (Interactive Connectivity Establishment).
ICE - это протокол, который существует до WebRTC и позволяет установить прямое соединение между двумя агентами без центрального сервера. Эти два агента могут находиться в одной сети или на противоположных концах земного шара.
ICE обеспечивает прямое подключение, но настоящая магия процесса подключения заключается в концепции “обхода NAT” и использовании STUN/TURN-серверов. Эти две концепции, которые мы подробнее исследуем позже, - все, что вам нужно для связи с ICE-агентом в другой подсети.
Когда два агента успешно установили ICE-соединение, WebRTC переходит к следующему шагу: установлению зашифрованного транспорта для обмена аудио, видео и данными между ними.
Защита транспортного уровня с помощью DTLS и SRTP #
Теперь, когда у нас есть двунаправленная связь (через ICE), нам нужно сделать нашу коммуникацию безопасной! Это делается с помощью еще двух протоколов, которые также существовали до WebRTC: DTLS (Datagram Transport Layer Security) и SRTP (Secure Real-Time Transport Protocol). Первый протокол, DTLS, - это просто TLS поверх UDP (TLS - криптографический протокол, используемый для защиты связи через HTTPS). Второй протокол, SRTP, используется для обеспечения шифрования пакетов данных RTP (Real-time Transport Protocol).
Сначала WebRTC подключается, выполняя DTLS-рукопожатие поверх соединения, установленного ICE. В отличие от HTTPS, WebRTC не использует центральный орган для сертификатов. Он просто утверждает, что сертификат, обмененный через DTLS, соответствует отпечатку, предоставленному через сигнализацию. Это DTLS-соединение затем используется для сообщений DataChannel.
Далее, WebRTC использует протокол RTP, защищенный с помощью SRTP, для передачи аудио/видео. Мы инициализируем нашу SRTP-сессию, извлекая ключи из согласованной DTLS-сессии.
Мы обсудим, почему передача медиа и данных имеют свои собственные протоколы, в следующей главе, но пока достаточно знать, что они обрабатываются отдельно.
Коммуникация с пирами через RTP и SCTP #
Теперь, когда у нас есть два WebRTC-агента, подключенные и защищенные, с установленной двунаправленной связью, давайте начнем общаться! Снова WebRTC будет использовать два существующих протокола: RTP (Real-time Transport Protocol) и SCTP (Stream Control Transmission Protocol). Мы используем RTP для обмена медиа, зашифрованными с помощью SRTP, и SCTP для отправки и получения сообщений DataChannel, зашифрованных с помощью DTLS.
RTP - это довольно минимальный протокол, но он предоставляет необходимые инструменты для реализации потоковой передачи в реальном времени. Самое важное в RTP - это гибкость для разработчика, позволяющая обрабатывать задержку, потерю пакетов и перегрузки по своему усмотрению. Мы обсудим это подробнее в главе о медиа.
Последний протокол в стеке - SCTP. Важная особенность SCTP заключается в том, что вы можете отключить надежную и упорядоченную доставку сообщений (среди многих других опций). Это позволяет разработчикам обеспечить необходимую задержку для систем реального времени.
Теперь мы закончили! Мы успешно установили двунаправленную и безопасную связь. Если у вас есть стабильное соединение между вашими WebRTC-агентами, это вся сложность, которая вам нужна. В следующем разделе мы обсудим, как WebRTC справляется с реальными проблемами потери пакетов и ограничениями пропускной способности.
WebRTC - набор протоколов #
WebRTC решает множество проблем. На первый взгляд технология может показаться чрезмерно сложной, но гениальность WebRTC заключается в его скромности. Он был создан не с предположением, что сможет решить все лучше. Вместо этого он объединил многие существующие технологии с единственной целью в единый, широко применимый пакет.
Это позволяет нам изучать и исследовать каждую часть индивидуально, не испытывая перегрузки. Хороший способ визуализировать это - ‘WebRTC-агент’ на самом деле является просто оркестратором многих различных протоколов.
Как работает API WebRTC? #
Этот раздел описывает, как JavaScript API WebRTC соотносится с протоколом WebRTC, описанным выше. Он не предназначен для подробной демонстрации API WebRTC, а скорее для создания ментальной модели того, как все связано. Если вы не знакомы ни с протоколом, ни с API, не волнуйтесь. Этот раздел будет интересно перечитать, когда вы узнаете больше!
new RTCPeerConnection
#
RTCPeerConnection
- это верхнеуровневый “сеанс WebRTC”. Он содержит все упомянутые выше протоколы. Подсистемы все выделены, но пока ничего не происходит.
addTrack
#
addTrack
создает новый RTP-поток. Для этого потока будет сгенерирован случайный Synchronization Source (SSRC). Этот поток будет находиться внутри Session Description, сгенерированной createOffer
в медиа-секции. Каждый вызов addTrack
создаст новый SSRC и медиа-секцию.
Сразу после установления SRTP-сессии эти медиа-пакеты начнут шифроваться с помощью SRTP и отправляться через ICE.
createDataChannel
#
createDataChannel
создает новый SCTP-поток, если SCTP-ассоциация не существует. SCTP не включен по умолчанию. Он запускается только когда одна сторона запрашивает канал данных.
Сразу после установления DTLS-сессии SCTP-ассоциация начнет отправлять пакеты, зашифрованные с помощью DTLS через ICE.
createOffer
#
createOffer
генерирует Session Description локального состояния для обмена с удаленным пиром.
Акт вызова createOffer
не меняет ничего для локального пира.
setLocalDescription
#
setLocalDescription
фиксирует все запрошенные изменения. Вызовы addTrack
, createDataChannel
и подобные являются временными до этого вызова. setLocalDescription
вызывается со значением, сгенерированным createOffer
.
Обычно после этого вызова вы отправите предложение удаленному пиру, который будет использовать его для вызова setRemoteDescription
.
setRemoteDescription
#
setRemoteDescription
- это способ информирования локального агента о состоянии удаленных кандидатов. Так акт ‘Сигнализации’ выполняется с помощью JavaScript API.
Когда setRemoteDescription
был вызван на обеих сторонах, WebRTC-агенты теперь имеют достаточно информации для начала связи “Peer-To-Peer” (P2P)!
addIceCandidate
#
addIceCandidate
позволяет WebRTC-агенту добавлять дополнительные удаленные ICE-кандидаты в любое время. Этот API отправляет ICE-кандидата прямо в подсистему ICE и не имеет другого эффекта для большего WebRTC-соединения.
ontrack
#
ontrack
- это обратный вызов, срабатывающий при получении RTP-пакета от удаленного пира. Входящие пакеты были объявлены в Session Description, переданном через setRemoteDescription
.
WebRTC использует SSRC и ищет связанный MediaStream
и MediaStreamTrack
, и вызывает этот обратный вызов с этими деталями.
oniceconnectionstatechange
#
oniceconnectionstatechange
- это обратный вызов, который срабатывает при изменении состояния ICE-агента. Когда происходит изменение сетевой связности, вы получаете об этом уведомление.
onconnectionstatechange
#
onconnectionstatechange
- это комбинация состояний ICE-агента и DTLS-агента. Вы можете наблюдать за этим, чтобы быть уведомленным, когда ICE и DTLS успешно завершены.