Хабрахабр

Опыт использования WebRTC. Лекция Яндекса

Что лучше использовать при разработке софта — нативные или веб-технологии? Холивар по этому поводу закончится ещё не скоро, но мало кто станет спорить, что нативные функции полезно продублировать для использования в браузерах или WebView. И если когда-то приложения для звонков существовали исключительно отдельно от браузера, то теперь их легко реализовать и в вебе. Разработчик Григорий Кузнецов объяснил, как пользоваться технологией WebRTC для P2P-соединений.

— Как вы все знаете, в последнее время появляется довольно много приложений, в основу которых заложен прямой обмен данными между двумя браузерами, то есть P2P. Это всевозможные мессенджеры, чаты, звонилки, видеоконференции. Также это могут быть приложения, которые производят какие-то распределенные вычисления. Пределы фантазии никак не ограничиваются.
Как же нам сделать подобную технологию? Представим, что мы хотим совершить звонок из одного браузера в другой. И пофантазируем, какие нам нужны шаги, чтобы этой цели достичь. В первую очередь кажется, что звонок — это наша картинка, наш голос, изображение, и нужно получить доступ к медиаустройствам, подключенным к компьютеру: к камере и к микрофону. После того, как вы получите доступ, вам необходимо, чтобы ваши два браузера, два клиента, друг друга нашли. Нужно помочь им как-то соединиться, достучаться, передать метаинформацию.

Все необходимые пункты у нас есть, мы готовы реализовать свой классный новый велосипед. Когда вы достучитесь, необходимо начать передавать данные в режиме P2P, то есть обеспечить передачу медиапотоков. Поэтому как классические инженеры давайте сначала подумаем, какие решения уже существуют. Но это шутка, мы с вами инженеры и понимаем, что это дорого, неоправданно и рискованно.

Она действительно умирает, и компания Adobe прекратит ее поддержку уже в 2020 году. В первую очередь — старая умирающая технология Adobe Flash. Технология действительно позволит вам получить доступ к вашим медиаустройствам, внутри нее вы сможете реализовать всю необходимую механику, чтобы помочь браузерам соединиться, чтобы они начали передавать информацию P2P, но вы опять изобретете свой велосипед, потому что нет единого стандарта, единого подхода к реализации данного способа передачи данных.

Так работает Skype для тех браузеров, которые не поддерживают более современные технологии. Вы можете написать для браузера плагин. Пользователи этого не любят и не хотят делать. Вам придется реализовывать свой велосипед, потому что нет единого стандарта, а еще это плохо для пользователей, так как пользователю придется себе в браузер инсталлировать какой-то плагин, совершать дополнительные действия.

Компания Voximplant использует ее, чтобы вы могли совершать свои звонки. И есть технология WebRTC — с помощью нее работают Google Hangouts, Facebook Messenger. Это новая развивающаяся технология, она появилась в 2011 году и продолжает развиваться. Давайте на ней остановимся подробнее. Получить доступ к камере и микрофону. Что же она позволяет делать? Естественно, она позволяет передавать медиапотоки в режиме реального времени. Установить P2P-соединение между двумя компьютерами, двумя браузерами. Кроме того, она позволяет передавать информацию, то есть любую бинарную дату вы тоже можете передавать P2P, можете сделать свою систему распределенных вычислений.

Мы можем сформировать всю необходимую метаинформацию о нас любимых, но как одному браузеру узнать о существовании другого? Важный момент: WebRTC не предоставляет браузерам способ найти друг друга. Рассмотрим пример. Как их соединить?

Первый клиент желает совершить звонок второму клиенту. Есть два клиента. Но остается открытым вопрос, как одному браузеру найти другой, как эту метаинформацию переслать, как проинициализировать вызов. WebRTC дает всю необходимую информацию, чтобы себя обозначить. Это дается на откуп разработчикам, мы можем использовать абсолютно любой способ, взять эту метаинформацию, распечатать на бумажке, отправить курьером, другой ее будет использовать, и все будет работать.

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

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

Второй клиент берет ее, использует, устанавливает себе, формирует ответ, и с помощью сигнального механизма пересылает ее на сигнальный сервер, тот в свою очередь ретранслирует ее первому клиенту. Сигнальный сервер по этому идентификатору устанавливает, какому именно клиенту нужно переадресовать нашу метаинформацию, и пересылает ее. Готово. Таким образом оба клиента в данный момент обладают всей необходимой датой и метаинформацией, чтобы установить P2P-соединение.

Давайте чуть подробнее рассмотрим, чем же именно обмениваются клиенты, они обмениваются SDP-датаграммой, Session Description Protocol.

Там есть информация об IP-адресе, о портах, которые используются, о том, какая именно информация гоняется между клиентами, что это такое — аудио, видео, какие кодеки используются. Это, по сути, текстовый файл, который содержит всю необходимую информацию, чтобы установить соединение. Все, что нам необходимо, там есть.

Там указан IP-адрес клиента, 192. Обратите внимание на вторую строчку. 0. 168. Очевидно, это IP-адрес компьютера, который находится в какой-то локальной сети. 15. Получится ли у них сделать это с такой датаграммой? Если у нас два компьютера, каждый из которых находится в локальной сети, каждый из которых знает свой IP-адрес в рамках этой сети, хотят созвониться. Как быть? Очевидно, нет, они же не знают внешних IP-адресов.

В интернете многие компьютеры скрыты за роутерами. Отойдем в сторону и посмотрим, как работает NAT. Когда пакет от компьютера в локальной сети идет на роутер, роутер смотрит, куда его нужно переадресовать. Есть локальные сети, внутри которых компьютеры знают свои адреса, есть роутер, который обладает внешним IP-адресом, и наружу все эти компьютеры торчат с IP-адресом этого роутера. Если на другой этой локальной сети, то он просто его ретранслирует, а если нужно его отправить вовне, в интернет, то составляется таблица маршрутизации.

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

Как жить, если есть NAT, если компьютеры торчат наружу под одним IP-адресом, а внутри знают о друг друге по другим?

Он описывает способы обхода NAT, способы установки соединения, если у нас есть NAT. На помощь приходит фреймфорк ICE — Internet Connectivity Establishment.

Этот фреймворк использует приписывание так называемого STUN-сервера.

Таким образом, в процессе установки P2P соединения, каждый из клиентов должен сделать по запросу к этому STUN-серверу, чтобы узнать свой IP-адрес, и сформировать дополнительную информацию, IceCandidate, и с помощью сигнального механизма также этим IceCandidate обменяться. Это такой специальный сервер, обращаясь к которому, вы можете узнать свой внешний IP-адрес. Тогда клиенты будут знать друг о друге с правильными IP-адресами, и смогут установить P2P соединение.

Например, когда компьютер скрыт за двойным NAT. Однако бывают более сложные случаи. В этом случае фреймворк ICE предписывает использование TURN-сервера.

Хорошая новость для разработчиков в том, что независимо от того, по какому из трех сценариев пошла установка соединения, находимся ли мы в локальной сети, нужно ли обратиться к STUN- или TURN-серверу, АPI-технология для нас будет идентичной. Это такой специальный сервер, который превращает соединение клиент-клиент, P2P, в соединение клиент-сервер-клиент, то есть выступает в роли ретранслятора. Мы просто в начале указываем конфигурацию ICE- и TURN-серверов, указываем, как к ним обратиться, и после этого технология делает для нас все под капотом.

Чтобы установить соединение, нужно выбрать и реализовать некий механизм сигнализации, некого посредника, который будет помогать нам пересылать метаинформацию. Небольшое резюме. WebRTC даст нам всю необходимую мету для этого.

Но чтобы его обойти, используем STUN-сервер, чтобы узнать свой внешний IP-адрес, и TURN-сервер используем в качестве ретранслятора. Нам предстоит побороться с NAT, это наш главный враг на этом этапе.

Про медиа-потоки. Что же именно мы передаем?

Треки внутри медиа-потока синхронизированы. Медиапотоки — это такие каналы, которые внутри себя содержат треки. Вы можете внутри медиапотока сделать любое количество треков, треками можно управлять по отдельности, например, вы можете приглушить аудио, оставив только картинку. Аудио и видео не будет расходиться, они будут идти с единым таймингом. Также вы можете передавать любое количество медиа-потоков, что позволяет вам, например, реализовать конференцию.

Поговорим про API. Как же получить доступ к медиа из браузера?

Это специальный объект, где вы указываете, к каким именно устройствам вы хотите получить доступ, к какой именно камере, к какому микрофону. Есть метод getUserMedia, который принимает на вход набор констрейнтов. В более современных реализациях технологии используются промисы. Указываете характеристики, которые хотите иметь, какое именно разрешение, и есть также два аргумента — successCallback и errorCallback, который вызывается в случае успеха или неудачи.

Есть также удобный метод enumerateDevices, который возвращает список всех подключенных к вашему компьютеру медиа-устройств, что дает вам возможность показать их пользователю, нарисовать какой-то селектор, чтобы пользователь выбрал, какую конкретно камеру он хочет использовать.

Когда мы выполняем соединение, то берем класс RTCPeerConnection, который возвращает объект peerConnection. Центральным объектом в API служит RTCPeerConnection. И есть важный ивент onicecandidate, который триггерится каждый раз, когда нам нужна помощь нашего сигнального механизма. В качестве конфигурации мы указываем набор ICE-серверов, то есть STUN- и TURN-серверов, к которым мы будем обращаться в процессе установки. То есть технология WebRTC сделала запрос, например, к STUN-серверу, мы узнали свой внешний IP-адрес, появился новый сформированный ICECandidate, и нам нужно переслать его с помощью стороннего механизма, ивент стриггерился.

Когда мы устанавливаем соединение и хотим проинициализировать вызов, мы используем метод createOffer(), чтобы сформировать начальную SDP, offer SDP, ту самую мета-информацию, которую нужно переслать партнеру.

Собеседник получает эту информацию по сигнальному механизму, устанавливает ее себе с помощью метода setRemoteDescription() и формирует ответ с помощью метода createAnswer(), который также с помощью сигнального механизма пересылается первому клиенту. Чтобы установить ее в PeerConnection, мы используем метод setLocalDescription().

Он получит наш поток и сможет его отобразить. Когда мы получили доступ к медиа, получили медиапоток, мы его передаем в наше P2P-соединение с помощью метода addStream, а наш собеседник узнает об этом, у него стриггерится ивент onaddstream.

Очень похоже на формирование обычного peerConnection, просто указываете RtpDataChannels: true и вызываете метод createDataChannel(). Также вы можете работать с дата-потоками. Подробно на этом останавливаться не буду, потому что такая работа очень похожа на работу с веб-сокетами.

WebRTC работает только по HTTPS, ваш сайт должен быть подписан сертификатом. Пару слов о безопасности. Технология не требует установки ничего дополнительного, никаких плагинов, и это хорошо. Медиапотоки тоже шифруются, используется DTLS. И не получится сделать шпионское приложение, сайт не будет подслушивать или подсматривать за пользователем, он покажет пользователю специальный промт, запросит у него доступ и получит его, только если пользователь разрешит доступ к аудио- и медиаустройствам.

В конце прошлого года добавилась поддержка Safari, то есть уже все современные браузеры умеют работать с этой технологией и мы можем смело ее использовать. Что касается поддержки браузеров — IE остается и останется красным.

В первую очередь это adapter. Хочу поделиться набором всяких полезностей, которые помогут вам, если вы желаете работать с WebRTC. Библиотека adapter нивелирует эту разницу и облегчает работу. Технологии все время развиваются, и есть разница в браузерных API. Также можете посмотреть на открытые реализации STUN- и TURN-сервера. Удобная библиотека для работы с дата-потоками — Peerjs. Большой набор туториалов, примеров, статей находится на страничке awesome-webrtc, очень рекомендую.

Во время разработки вы можете в адресной строке набрать специальную команду — например в браузере Chrome это Chrome://webrtc-internals. Последняя незаменимая при дебаге полезность — webrtc-internals. Там будут и последовательности вызовов в методах, и все датаграммы, которыми обмениваются браузеры, и графики, которые каким-то характеризуют образом ваше соединение. У вас откроется страница со всей информацией о вашем текущем WebRTC-соединении. Спасибо за внимание. В общем, там будет вся информация, которая понадобится при дебаге и разработке.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть