Технология webrtc. WebRTC, аудио и видео-чат прямо в браузере без какого-либо приложения. Видео по тестированию трансляции с веб-камеры через WebRTC-сервер

WebRTC (сокращенно от Web real-time communications) – это технология, которая позволяет передавать аудио и видео потоковые данные между браузерами и мобильными приложениями.


Разработка этой технологии составляет конкуренцию Skype. WebRTC можно использовать для организации видеоконференций напрямую в браузере. Проект имеет открытый исходный код и активно продвигается компанией Google и в частности командой разработки браузера Google Chrome.


Браузеры пользователей благодаря технологии WebRTC могут передавать данные друг другу напрямую. WebRTC не нужен отдельный сервер, который бы хранил и обрабатывал данные. Все данные обрабатываются напрямую бразерами и мобильными приложениями конечных пользователей.


Технология WebRTC поддерживается всеми популярными браузерами Mozilla Firefox, Opera, Google Chrome (и всеми браузерами на базе Google Chrome), а также мобильными приложениями на базе Android и iOS.

Опасность WebRTC

Опасность технологии WebRTC заключается в определении вашего реального IP адреса. Так как подключение идет напрямую с другим пользователем, браузером, веб-сайтом или мобильным приложением, то настройки сети игнорируются. Для создания аудио и видеосвязи браузеры должны обменяться внешними и локальными IP адресами.

Анонимный VPN сервис решает данную проблему и скрывает реальный IP адрес. Максимум, что может быть обнаружено – это локальный IP адрес, присвоенный пользователю VPN сетью. Это не опасно, так как такие же локальные IP адреса будут показываться, если вы используете роутер для раздачи Интернета.


Если вы используете прокси, тогда WebRTC сможет определить ваш реальный IP адрес за прокси или IP адрес VPN сервера, если вы используете цепочку VPN + прокси.


WebRTC также определяет ваш реальный IP адрес при использовании сети Tor .


Самое лучшее решение – отключить технологию WebRTC, если вы этим не пользуетесь.

Как отключить WebRTC в браузерах

Быстрая навигация по этой странице.

Как отключить WebRTC в Mozilla Firefox

Браузер Mozilla Firefox - это единственный браузер, позволяющий отключить технологию WebRTC без установки дополнительных плагинов.

Ручная настройка

Если вы не используете технологию WebRTC, то можете полностью отключить ее. В случае, когда необходимо использовать WebRTC периодически удобнее .

Чтобы отключить технологию WebRTC в Mozilla Firefox необходимо в адресной строке браузера ввести следующий текст и нажать кнопку Enter.

About:config


Нажмите, кнопку Я принимаю на себя риск.


Выполните следующее:

  • В поисковую строку введите текст и нажмите Enter.
  • media.peerconnection.enabled
  • Нажмите правой кнопкой мышки на строку и выберите Переключить. Или дважды кликните по строке.

  • После этих действий WebRTC будет отключен.

    Настройка через плагин WebRTC Control

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

    Откройте Дополнения.


    Выберите:

  • Раздел Поиск
  • Введите название плагина в поисковую строку: WebRTC Control
  • Нажмите кнопку Установить

  • Как отключить WebRTC в браузере Opera

    Для отключения WebRTC в браузере Opera перейдите в галерею Расширений.


    Выполните следующие действия:

  • Введите название плагина в поисковой строке: WebRTC Control
  • Нажмите на плагин

  • Нажмите Добавить в Opera.


    Активируйте плагин. Иконка плагина должна стать синего цвета для блокировки WebRTC.

    Как отключить WebRTC в Google Chrome

    Для отключения WebRTC в браузере Google Chrome перейдите в раздел Расширения.


    Пролистайте страницу вниз и нажмите Еще расширения.


    Выполните следующие действия:

  • Введите в поисковую строку название плагина: WebRTC Control
  • Нажмите кнопку Установить.


  • Активируйте плагин. Иконка плагина должна стать синего цвета для блокировки WebRTC.

    Как отключить WebRTC в Яндекс Браузере

    Для отключения WebRTC в Яндекс Браузере перейдите в раздел Дополнения.


    Пролистайте страницу вниз и нажмите Каталог расширений для Яндекс Браузера.


    Выполните действия:

  • Введите в поисковой строке название плагина: WebRTC Control
  • Нажмите на плагин для установки.

  • Нажмите Добавить в Яндекс Браузер.


    Нажмите Установить расширение.


    Активируйте плагин. Иконка плагина должна стать синего цвета для блокировки WebRTC.

    Как отключить WebRTC в браузере SRWare Iron

    Браузер SRWare Iron сделан на базе Google Chrome.

    Установите плагин WebRTC Control по инструкции для .

    WebRTC – это API, предоставляемое браузером и позволяющее организовать P2P соединение и передачу данных напрямую между браузерами. В Интернете довольно много руководств по написанию собственного видео-чата при помощи WebRTC. Например, вот статья на Хабре. Однако, все они ограничиваются соединением двух клиентов. В этой статье я постараюсь рассказать о том, как при помощи WebRTC организовать подключение и обмен сообщениями между тремя и более пользователями.

    Интерфейс RTCPeerConnection представляет собой peer-to-peer подключение между двумя браузерами. Чтобы соединить трех и более пользователей, нам придется организовать mesh-сеть (сеть, в которой каждый узел подключен ко всем остальным узлам).
    Будем использовать следующую схему:

  • При открытии страницы проверяем наличие ID комнаты в location.hash
  • Если ID комнаты не указано, генерируем новый
  • Отправляем signalling server"у сообщение о том, что мы хотим присоединиться к указанной комнате
  • Signalling server разсылает остальным клиентам в этой комнате оповещение о новом пользователе
  • Клиенты, уже находящиеся к комнате, отправляют новичку SDP offer
  • Новичок отвечает на offer"ы
  • 0. Signalling server

    Как известно, хоть WebRTC и предоставляет возможность P2P соединения между браузерами, для его работы всё равно требуется дополнительный транспорт для обмена сервисными сообщениями. В этом примере в качестве такого транспорта выступает WebSocket сервер, написанный на Node.JS с использованием socket.io:

    Var socket_io = require("socket.io"); module.exports = function (server) { var users = {}; var io = socket_io(server); io.on("connection", function(socket) { // Желание нового пользователя присоединиться к комнате socket.on("room", function(message) { var json = JSON.parse(message); // Добавляем сокет в список пользователей users = socket; if (socket.room !== undefined) { // Если сокет уже находится в какой-то комнате, выходим из нее socket.leave(socket.room); } // Входим в запрошенную комнату socket.room = json.room; socket.join(socket.room); socket.user_id = json.id; // Отправялем остальным клиентам в этой комнате сообщение о присоединении нового участника socket.broadcast.to(socket.room).emit("new", json.id); }); // Сообщение, связанное с WebRTC (SDP offer, SDP answer или ICE candidate) socket.on("webrtc", function(message) { var json = JSON.parse(message); if (json.to !== undefined && users !== undefined) { // Если в сообщении указан получатель и этот получатель известен серверу, отправляем сообщение только ему... users.emit("webrtc", message); } else { // ...иначе считаем сообщение широковещательным socket.broadcast.to(socket.room).emit("webrtc", message); } }); // Кто-то отсоединился socket.on("disconnect", function() { // При отсоединении клиента, оповещаем об этом остальных socket.broadcast.to(socket.room).emit("leave", socket.user_id); delete users; }); }); };

    1. index.html

    Исходный код самой страницы довольно простой. Я сознательно не стал уделять внимание верстке и прочим красивостям, так как это статья не об этом. Если кому-то захочется, сделать ее красивой, особого труда не составит.

    WebRTC Chat Demo Connected to 0 peers
    Send

    2. main.js 2.0. Получение ссылок на элементы страницы и интерфейсы WebRTC var chatlog = document.getElementById("chatlog"); var message = document.getElementById("message"); var connection_num = document.getElementById("connection_num"); var room_link = document.getElementById("room_link");

    Нам по прежнему приходится использовать браузерные префиксы для обращения к интерфейсам WebRTC.

    Var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;

    2.1. Определение ID комнаты

    Тут нам понадобится функция, для генерации уникального идентификатора комнаты и пользователя. Будем использовать для этих целей UUID.

    Function uuid () { var s4 = function() { return Math.floor(Math.random() * 0x10000).toString(16); }; return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4(); }

    Теперь попробуем вытащить идентификатор комнаты из адреса. Если такового не задано, сгенерируем новый. Выведем на страницу ссылку на текущую комнату, и, за одно, сгенерируем идентификатор текущего пользователя.

    Var ROOM = location.hash.substr(1); if (!ROOM) { ROOM = uuid(); } room_link.innerHTML = "Link to the room"; var ME = uuid();

    2.2. WebSocket

    Сразу при открытии страницы подключимся к нашему signalling server"у, отправим запрос на вход в комнату и укажем обработчики сообщений.

    // Указываем, что при закрытии сообщения нужно отправить серверу оповещение об этом var socket = io.connect("", {"sync disconnect on unload": true}); socket.on("webrtc", socketReceived); socket.on("new", socketNewPeer); // Сразу отправляем запрос на вход в комнату socket.emit("room", JSON.stringify({id: ME, room: ROOM})); // Вспомогательная функция для отправки адресных сообщений, связанных с WebRTC function sendViaSocket(type, message, to) { socket.emit("webrtc", JSON.stringify({id: ME, to: to, type: type, data: message})); }

    2.3. Настройки PeerConnection

    Большинство провайдеров предоставляем подключение к Интернету через NAT. Из-за этого прямое подключение становится не таким уж тривиальным делом. При создании соединения нам нужно указать список STUN и TURN серверов, которые браузер будет пытаться использовать для обхода NAT. Так же укажем пару дополнительных опций для подключения.

    Var server = { iceServers: [ {url: "stun:23.21.150.121"}, {url: "stun:stun.l.google.com:19302"}, {url: "turn:numb.viagenie.ca", credential: "your password goes here", username: "[email protected]"} ] }; var options = { optional: [ {DtlsSrtpKeyAgreement: true}, // требуется для соединения между Chrome и Firefox {RtpDataChannels: true} // требуется в Firefox для использования DataChannels API ] }

    2.4. Подключение нового пользователя

    Когда в комнату добавляется новый пир, сервер отправляет нам сообщение new . Согласно обработчикам сообщений, указанным выше, вызовется функция socketNewPeer .

    Var peers = {}; function socketNewPeer(data) { peers = { candidateCache: }; // Создаем новое подключение var pc = new PeerConnection(server, options); // Инициализирууем его initConnection(pc, data, "offer"); // Сохраняем пира в списке пиров peers.connection = pc; // Создаем DataChannel по которому и будет происходить обмен сообщениями var channel = pc.createDataChannel("mychannel", {}); channel.owner = data; peers.channel = channel; // Устанавливаем обработчики событий канала bindEvents(channel); // Создаем SDP offer pc.createOffer(function(offer) { pc.setLocalDescription(offer); }); } function initConnection(pc, id, sdpType) { pc.onicecandidate = function (event) { if (event.candidate) { // При обнаружении нового ICE кандидата добавляем его в список для дальнейшей отправки peers.candidateCache.push(event.candidate); } else { // Когда обнаружение кандидатов завершено, обработчик будет вызван еще раз, но без кандидата // В этом случае мы отправялем пиру сначала SDP offer или SDP answer (в зависимости от параметра функции)... sendViaSocket(sdpType, pc.localDescription, id); // ...а затем все найденные ранее ICE кандидаты for (var i = 0; i < peers.candidateCache.length; i++) { sendViaSocket("candidate", peers.candidateCache[i], id); } } } pc.oniceconnectionstatechange = function (event) { if (pc.iceConnectionState == "disconnected") { connection_num.innerText = parseInt(connection_num.innerText) - 1; delete peers; } } } function bindEvents (channel) { channel.onopen = function () { connection_num.innerText = parseInt(connection_num.innerText) + 1; }; channel.onmessage = function (e) { chatlog.innerHTML += "Peer says: " + e.data + ""; }; }

    2.5. SDP offer, SDP answer, ICE candidate

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

    Function socketReceived(data) { var json = JSON.parse(data); switch (json.type) { case "candidate": remoteCandidateReceived(json.id, json.data); break; case "offer": remoteOfferReceived(json.id, json.data); break; case "answer": remoteAnswerReceived(json.id, json.data); break; } }

    2.5.0 SDP offer function remoteOfferReceived(id, data) { createConnection(id); var pc = peers.connection; pc.setRemoteDescription(new SessionDescription(data)); pc.createAnswer(function(answer) { pc.setLocalDescription(answer); }); } function createConnection(id) { if (peers === undefined) { peers = { candidateCache: }; var pc = new PeerConnection(server, options); initConnection(pc, id, "answer"); peers.connection = pc; pc.ondatachannel = function(e) { peers.channel = e.channel; peers.channel.owner = id; bindEvents(peers.channel); } } } 2.5.1 SDP answer function remoteAnswerReceived(id, data) { var pc = peers.connection; pc.setRemoteDescription(new SessionDescription(data)); } 2.5.2 ICE candidate function remoteCandidateReceived(id, data) { createConnection(id); var pc = peers.connection; pc.addIceCandidate(new IceCandidate(data)); } 2.6. Отправка сообщения

    При нажатии на кнопку Send вызывается функция sendMessage . Всё, что она делает, это проходится по списку пиров, и пытается отправить всем указанное сообщение.

    Привет друзья, как вы уже знаете, мы сообщаем вам регулярно новые технологии, сегодня я представлю WebRTC, технология, разработанная компанией Google, которая позволяет пользователям говорить непосредственно в браузере видео и аудио, не требуя, что использование plugin- Веб-сайты или приложения. Видео и аудио прямое соединение между пользователями осуществляется непосредственно в браузере.
    Технология WebRTC поддерживается в Mozilla Firefox браузеров Google Chrome и на любой операционной системе, скоро присоединится и Opera.
    Что такое WebRTC и что?
    WebRTC короток для Web Real Time Comunication, эта технология позволяет открывать аудио и видео чатов непосредственно в браузере без необходимости других плагинов, приложений или услуг в Интернете для этого. Подключение осуществляется непосредственно из браузера в браузере.
    Если известные услуги (Skype, Yahoo Messenger, Apple FaceTime, Google Hago и т.д.) требуют сервер, который соединяет пользователей, чтобы инициировать и управлять трафиком. Используя эти услуги нам нужно зарегистрироваться и установил список клиентов и контактов.
    С WebRTC нам не нужны серверы, приложения или серверы, которые подключаются к заступиться.
    WebRTC преимущества:
    1. Нет больше приложений, потребляющее использование ресурсов и аккумулятора.
    2. В чатах более частные (относительно).
    3. Как связаться можно сделать на местном уровне, а не Flos США серверы для локальных соединений.
    4. Простота, удобство использования.
    5. Возможность дальнейшего развития, и в других направлениях.
    6. Связь стабильна и не зависит от внешних соединений, которые иногда крайне нестабильным.
    В учебнике я использовал демо, что люди в Google разработали, это демо довольно просто, более расширенные возможности и более быстрые соединения могут использовать один из приложений, которые поддерживают WebRTC, они проще в использовании. Скоро мы будем делать учебник и о приложениях WebRTC.
    Как использовать WebRTC демо?
    Очень просто нажмите на ссылку ниже, он автоматически генерирует чат. связать эту комнату, вы должны отправить друг / подруга, которую вы хотите, чтобы войти в контакт.
    Друг / подруга и ваш, но вы должны использовать только самые последние версии Mozilla Firefox или Google Chrome.

    Demo WebRTC (Вводный чат аудио - видео)

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

    WebRTC (Web Real-Time Communications) - это технология, которая позволяет Web-приложениям и сайтам захватывать и выборочно передавать аудио и/или видео медиа-потоки, а также обмениваться произвольными данными между браузерами, без обязательного использования посредников. Набор стандартов, которые включает в себя технология WebRTC, позволяет обмениваться данными и проводить пиринговые телеконференции, без необходимости пользователю устанавливать плагины или любое другое стороннее программное обеспечение.

    WebRTC состоит из нескольких взаимосвязанных программных интерфейсов (API) и протоколов, которые работают вместе. Документация, которую вы здесь найдете, поможет вам понять основы WebRTC, как настроить и использовать соединение для передачи данных и медиа-потока, и многое другое.

    Совместимость

    Поскольку, реализация WebRTC находиться в процессе становления и каждый браузер имеет и WebRTC функций, настоятельно рекомендуем использовать полифил-библиотеку Adapter.js , от Google, до начала работы над вашим кодом.

    Adapter.js использует клинья и полифилы для гладкой стыковки различий в реализациях WebRTC среди контекстов, его поддерживающих. Adapter.js также обрабатывает префиксы производителей, и иные различия именования свойств, облегчая процесс разработки на WebRTC, с наиболее совместимым результатом. Библиотека так же доступна как NPM пакет .

    Для дальнейшего изучения библиотеки Adapter.js, смотрим .

    Понятия и использование WebRTC

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

    Соединение между двумя узлами представлено как объект интерфейса RTCPeerConnection . Как только соединение установлено и открыто, используя объект RTCPeerConnection , медиапотоки ( MediaStream s) и/или каналы данных ( RTCDataChannel s) могут быть добавлены в соединение.

    Медиа потоки могут состоять из любого количества треков (дорожек) медиаинформации. Эти треки, представлены объектами интерфейса MediaStreamTrack , и могут содержать один или несколько типов медиаданных, включая аудио, видео, текст (такие как субтитры или название глав). Большинство потоков состоят, как минимум, только из одного аудио трека (одной аудио дорожки), или видео дорожки, и могут быть отправлены и получены, как потоки (медиаданные в настоящим времени) или сохранены в файл.

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

    more details and links to relevant guides and tutorials needed

    WebRTC интерфейсы

    По причине того, что WebRTC предоставляет интерфейсы, работающие совместно для выполнения различных задач, мы разделили их на категории. Смотрите алфавитный указатель боковой панели для быстрой навигации.

    Настройка соединения и управление

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

    RTCPeerConnection Представляет WebRTC соединение между локальным компьютером и удаленным узлом. Используется для обработки успешной передачи данных между двумя узлами. RTCSessionDescription Представляет параметры сессии. Каждый RTCSessionDescription содержит описания типа , показывающего какую часть (предложение/ответ) процесса переговоров он описывает, и SDP -дескриптор сессии. RTCIceCandidate Представляет собой кандидата сервера установки интернет соединения (ICE) для установленовки соединения RTCPeerConnection . RTCIceTransport Представляет информацию о средстве подключения к Интернету (ICE). RTCPeerConnectionIceEvent Представляет события, которые происходят в отношении кандидатов ICE, обычно RTCPeerConnection . Один тип передается данному объекту события: icecandidate . RTCRtpSender Управляет кродированием и передачей данных через объект типа MediaStreamTrack для объекта типа RTCPeerConnection . RTCRtpReceiver Управляет получением и декодированием данных через объект типа MediaStreamTrack для объекта типа RTCPeerConnection . RTCTrackEvent Указывает на то, что новый входящий объект типа MediaStreamTrack был создан и объект типа RTCRtpReceiver был добавлен в объект RTCPeerConnection . RTCCertificate Представляет сертификат, который использует объект RTCPeerConnection . RTCDataChannel Представляет двунапрвленный канал данных между двумя узлами соединения. RTCDataChannelEvent Представляет события, которые возникают при присоединении объекта типа RTCDataChannel к объекту типа RTCPeerConnection datachannel . RTCDTMFSender Управляет кодированием и передачей двутональной мультичастотной (DTMF) сигнализацией для объекта типа RTCPeerConnection . RTCDTMFToneChangeEvent Указывает на входящее событие изменение тона двутоновой мультичастотной сигнализации (DTMF). Это событие не всплывает (если не указано иначе) и не является отменяемым (если не указано иначе). RTCStatsReport Ассинхронно сообщает статус для переданного объекта типа MediaStreamTrack . RTCIdentityProviderRegistrar Регистрирует провайдер идентификации (idP). RTCIdentityProvider Активирует возможность браузеру запросить создание или проверку обяъвления идентификации. RTCIdentityAssertion Представляет идентификатор удаленного узла текущего соединения. Если узел еще не установлен и подтвержден, ссылка на интерфейс вернет null . После установки не изменяется. RTCIdentityEvent Представляет объект события объявление идентификатора провайдером идентификации (idP). Событие объекта типа RTCPeerConnection . Один тип передается этому событию identityresult . RTCIdentityErrorEvent Представляет объект события ошибки, связанной с провайдером идентификации (idP). Событие объекта типа RTCPeerConnection . Два типа ошибки передаются этому событию: idpassertionerror и idpvalidationerror . Руководства Обзор архитектуры WebRTC Под API, который применяют разработчики, чтобы создавать и использовать WebRTC, расположен набор сетевых протоколов и стандартов соединения. Этот обзор - витрина этих стандартов. WebRTC позволяет вам организовать соединение в режиме узел-узел для передачи произвольных данных, аудио-, видео-потоков или любую их комбинацию в браузере. В этой статье мы взглянем на жизнь WebRTC-сессии, начиная с установки соединения и пройдем весь путь до его завершения, когда оно больше не нужно. Обзор WebRTC API WebRTC состоит из нескольких взаимосвязанных программных интерфейсов (API) и протоколов, которые работают вместе, чтобы обеспечить поддержку обмена данными и медиа-потоками между двумя и более узлами. В этой статье представлен краткий обзор каждого из этих API и какую цель он преследует. Основы WebRTC Эта статья проведет вас через создание кросс-браузерного RTC-приложения. К концу этой статьи вы должны иметь работающий дата- и медиа-канал, работающий в режиме точка-точка. Протоколы WebRTC В этой статье представлены протоколы, в дополнение к которым создан API WebRTC. Это руководство описывает как вы можете использовать соединение узел-узел и связанный

    Большинство материала по WebRTC сосредоточено на прикладном уровне написания кода и не способствует пониманию технологии. Попробуем углубиться и узнать как происходит соединение, что такое дескриптор сессии и кандидаты, для чего нужны STUN и TURN сервера.

    WebRTC Введение

    WebRTC – технология, ориентированная на браузеры, которая позволяет соединить два клиента для видео-передачи данных. Основные особенности – внутренняя поддержка браузерами (не нужны сторонние внедряемые технологии типа adobe flash ) и способность соединять клиентов без использования дополнительных серверов – соединение peer-to-peer (далее, p2p ).

    Установить соединение p2p – довольно трудная задача, так как компьютеры не всегда обладают публичными IP адресами, то есть адресами в интернете. Из-за небольшого количества IPv4 адресов (и для целей безопасности) был разработан механизм NAT , который позволяет создавать приватные сети, например, для домашнего использования. Многие домашние роутеры сейчас поддерживают NAT и благодаря этому все домашние устройства имеют выход в интернет, хотя провайдеры интернета обычно предоставляют один IP адрес. Публичные IP адреса - уникальны в интернете, а приватные нет. Поэтому соединиться p2p - трудно.

    Для того, чтобы понять это лучше, рассмотрим три ситуации: оба узла находятся в одной сети (Рисунок 1) , оба узла находятся в разных сетях (один в приватной, другой в публичной) (Рисунок 2) и оба узла находятся в разных приватных сетях с одинаковыми IP адресами (Рисунок 3) .

    Рисунок 1: Оба узла в одной сети

    Рисунок 2: Узлы в разных сетях (один в приватной, другой в публичной)

    Рисунок 3: Узлы в разных приватных сетях, но с численно равными адресами

    На рисунках выше первая буква в дву-символьных обозначениях означает тип узла (p = peer , r = router ). На первом рисунке ситуация благоприятная: узлы в своей сети вполне идентифицируются сетевыми IP адресами и поэтому могут подключаться к друг другу напрямую. На втором рисунке имеем две разные сети, у которых похожие нумерации узлов. Здесь появляются маршрутизаторы (роутеры), у которых есть два сетевых интерфейса – внутри своей сети и вне своей сети. Поэтому у них два IP адреса. Обычные узлы имеют только один интерфейс, через который они могут общаться только в своей сети. Если они передают данные кому-то вне своей сети, то только с помощью NAT внутри маршрутизатора (роутера) и поэтому видимы для других под IP адресом роутера – это их внешний IP адрес. Таким образом, у узла p1 есть внутренний IP = 192.168.0.200 и внешний IP = 10.50.200.5 , причем последний адрес будет внешним также и для всех других узлов в его сети . Похожая ситуация и для узла p2 . Поэтому их связь невозможна, если использовать только их внутренние (свои) IP адреса. Можно воспользоваться внешними адресами, то есть адресами роутеров, но, так как у всех узлов в одной приватной сети один и тот же внешний адрес, то это довольно затруднительно. Это проблема решается с помощью механизма NAT

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

    WebRTC успешно справляется с такими проблемами, используя протокол ICE , который, правда, требует использования дополнительных серверов (STUN , TURN ). Обо всем этом ниже.

    Две фазы WebRTC

    Чтобы соединить два узла через протокол WebRTC (или просто RTC , если связываются два iPhone ‘a) необходимо провести некие предварительные действия для установления соединения. Это первая фаза – установка соединения. Вторая фаза – передача видео-данных.

    Сразу стоит сказать, что, хоть технология WebRTC в своей работе использует множество различных способов коммуникации (TCP и UDP ) и имеет гибкое переключение между ними, эта технология не имеет протокола для передачи данных о соединении . Не удивительно, ведь подключить два узла p2p не так-то просто. Поэтому необходимо иметь некоторый дополнительный способ передачи данных, никак не связанный с WebRTC . Это может быть сокетная передача, протокол HTTP , это может быть даже протокол SMTP или Почта России . Этот механизм передачи начальных данных называется сигнальным . Передавать нужно не так много информации. Все данные передаются в виде текста и делятся на два типа – SDP и Ice Candidate . Первый тип используется для установления логического соединения, а второй для физического . Подробно обо всем этом позже, а пока лишь важно помнить, что WebRTC даст нам некую информацию, которую нужно будет передать другому узлу. Как только мы передадим всю нужную информацию, узлы смогут соединиться и больше наша помощь нужна не будет. Таким образом, сигнальный механизм, который мы должны реализовать отдельно , будет использоваться только при подключении , а при передаче видео-данных использоваться не будет.

    Итак, рассмотрим первую фазу – фазу установки соединения. Она состоит из нескольких пунктов. Рассмотрим эту фазу сначала для узла, который инициирует соединение, а потом для ожидающего.

    • Инициатор (звонящий – caller ):
    • Предложение начать видео-передачу данных (createOffer)
    • Получение своего SDP SDP )
    • Получение своих Ice candidate Ice candidate )
    • Ожидающий звонка (callee ):
    • Получение локального (своего) медиа потока и установка его для передачи (getUserMediaStream)
    • Получение предложения начать видео-передачу данных и создание ответа (createAnswer)
    • Получение своего SDP объекта и передача его через сигнальный механизм (SDP )
    • Получение своих Ice candidate объектов и передача их через сигнальный механизм (Ice candidate )
    • Получение удаленного (чужого) медиа потока и отображение его на экране (onAddStream)

    Отличие лишь во втором пункте.

    Несмотря на кажущуюся запутанность шагов здесь их на самом деле три: отправка своего медиа потока (п.1), установка параметров соединения (пп.2-4), получение чужого медиа потока (п.5). Самый сложный – второй шаг, потому что он состоит из двух частей: установление физического и логического соединения. Первая указывает путь , по которому должны идти пакеты, чтобы дойти от одного узла сети до другого. Вторая указывает параметры видео/аудио – какое использовать качество, какие использовать кодеки.

    Мысленно этап createOffer или createAnswer следует соединить с этапами передачи SDP и Ice candidate объектов.

    Основные сущности Медиа потоки (MediaStream)

    Основной сущностью является медиа поток, то есть поток видео и аудио данных, картинка и звук. Медиа потоки бывают двух типов – локальные и удаленные. Локальный получает данные от устройств входа (камера, микрофон), а удаленный по сети. Таким образом у каждого узла есть и локальный, и удаленный поток. В WebRTC для потоков существует интерфейс MediaStream и также существует подинтерфейс LocalMediaStream специально для локального потока. В JavaScript можно столкнуться только с первым, а если использовать libjingle , то можно столкнуться и со вторым.

    В WebRTC существует довольно запутанная иерархия внутри потока. Каждый поток может состоять из нескольких медиа дорожек (MediaTrack ), которые в свою очередь могут состоять из нескольких медиа каналов (MediaChannel ). Да и самих медиа потоков может быть тоже несколько.

    Рассмотрим все по порядку. Для этого будем держать в уме некоторый пример. Допустим, что мы хотим передавать не только видео себя, но и видео нашего стола, на котором лежит листок бумаги, на котором мы собираемся что-то писать. Нам понадобится два видео (мы + стол) и одно аудио (мы). Ясно, что мы и стол стоит разделить на разные потоки, потому что эти данные, наверное, слабо зависят друг от друга. Поэтому у нас будет два MediaStream ‘a – один для нас и один для стола. Первый будет содержать и видео, и аудио данные, а второй – только видео (Рисунок 4).

    Рисунок 4: Два различных медиа потока. Один для нас, один для нашего стола

    Сразу ясно, что медиа поток как минимум должен включать в себя возможность содержать данные разных типов - видео и аудио. Это учтено в технологии и поэтому каждый тип данных реализуется через медиа дорожку MediaTrack . У медиа дорожки есть специальное свойство kind , которое и определяет, что перед нами – видео или аудио (Рисунок 5)

    Рисунок 5: Медиа потоки состоят из медиа дорожек

    Как будет всё происходить в программе? Мы создадим два медиа потока. Потом создадим две видео дорожки и одну аудио дорожку. Получим доступ к камерам и микрофону. Укажем каждой дорожке какое устройство использовать. Добавим видео и аудио дорожку в первый медиа поток и видео дорожку от другой камеры во второй медиа поток.

    Но как мы различим медиа потоки на другом конце соединения? Для этого каждый медиа поток имеет свойство label – метка потока, его название (Рисунок 6). Такое же свойство имеют и медиа дорожки. Хотя на первый взгляд кажется, что видео от звука можно отличить и другими способами.

    Рисунок 6: Медиа потоки и дорожки идентифицируются метками

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

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

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

    В конце стоит подумать о стерео звуке. Как известно стерео звук – это два разных звука. И передавать их надо тоже отдельно. Для этого используются каналы MediaChannel . Медиа дорожка звука может иметь много каналов (например, 6, если нужен звук 5+1). Внутри медиа дорожки каналы, разумеется тоже синхронизированы . Для видео обычно используется только один канал, но могут использоваться и несколько, например, для наложения рекламы.

    Резюмируя: мы используем медиа поток для передачи видео и аудио данных. Внутри каждого медиа потока данные синхронизированы. Мы можем использовать несколько медиа потоков, если синхронизация нам не нужна. Внутри каждого медиа потока есть медиа дорожки двух видов – для видео и для аудио. Дорожек обычно не больше двух, но может быть и больше, если нужно передавать несколько разных видео (собеседника и его стола). Каждая дорожка может состоять из нескольких каналов, что используется обычно только для стерео звука.

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

    Дескриптор сессии (SDP)

    У разных компьютеров всегда будут разные камеры, микрофоны, видеокарты и прочее оборудование. Существует множество параметров, которыми они обладают. Все это необходимо скоординировать для медиа передачи данных между двумя узлами сети. WebRTC делает это автоматически и создает специальный объект – дескриптор сессии SDP . Передайте этот объект другому узлу, и можно передавать медиа данные. Только связи с другим узлом пока нет .

    Для этого используется любой сигнальный механизм. SDP можно передать хоть через сокеты, хоть человеком (сообщить его другому узлу по телефону), хоть Почтой России. Всё очень просто – Вам дадут уже готовый SDP и его нужно переслать. А при получении на другой стороне – передать в ведомство WebRTC . Дескриптор сессии хранится в виде текста и его можно изменить в своих приложениях, но, как правило, это не нужно. Как пример, при соединении десктоп↔телефон иногда требуется принудительно выбирать нужный аудио кодек.

    Обычно при установке соединения необходимо указывать какой-то адрес, например URL . Здесь в этом нет необходимости, так как через сигнальный механизм Вы сами отправите данные по назначению. Чтобы указать WebRTC , что мы хотим установить p2p соединение нужно вызвать функцию createOffer . После вызова этой функции и указания ей специального callback ‘a будет создан SDP объект и передан в этот же callback . Все, что от Вас требуется – передать этот объект по сети другому узлу (собеседнику). После этого на другом конце через сигнальный механизм придут данные, а именно этот SDP объект. Этот дескриптор сессии для этого узла чужой и поэтому несет полезную информацию. Получение этого объекта – сигнал к началу соединения. Поэтому Вы должны согласиться на это и вызвать функцию createAnswer . Она – полный аналог createOffer . Снова в Ваш callback передадут локальный дескриптор сессии и его нужно будет передать по сигнальному механизму обратно.

    Стоит отметить, что вызывать функцию createAnswer можно только после получения чужого SDP объекта. Почему? Потому что локальный SDP объект, который будет генерироваться при вызове createAnswer , должен опираться на удаленный SDP объект. Только в таком случае возможно скоординировать свои настройки видео с настройками собеседника. Также не стоит вызывать createAnswer и createOffer до получения локального медиа потока – им будет нечего писать в SDP объект .

    Так как в WebRTC есть возможность редактирования SDP объекта, то после получения локального дескриптора его нужно установить. Это может показаться немного странным, что нужно передавать WebRTC то, что она сама нам дала, но таков протокол. При получении удаленного дескриптора его нужно тоже установить. Поэтому Вы должны на одном узле установить два дескриптора – свой и чужой (то есть локальный и удаленный).

    После такого рукопожатия узлы знают о пожеланиях друг друга. Например, если узел 1 поддерживает кодеки A и B , а узел 2 поддерживает кодеки B и C , то, так как каждый узел знает свой и чужой дескрипторы, оба узла выберут кодек B (Рисунок 7). Логика соединения теперь установлена, и можно передавать медиа потоки, но есть другая проблема – узлы по-прежнему связаны лишь сигнальным механизмом.


    Рисунок 7: Согласование кодеков

    Кандидаты (Ice candidate)

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

    Итак, соединение уже установлено (логическое соединение), но пока нет пути, по которому узлы сети могут передавать данные. Здесь не всё так просто, но начнем с простого. Пусть узлы находятся в одной приватной сети. Как мы уже знаем, они могут легко соединяться друг с другом по своим внутренним IP адресам (или быть может, по каким-то другим, если используется не TCP/IP ).

    Через некоторые callback ‘и WebRTC сообщает нам Ice candidate объекты. Они тоже приходят в текстовой форме и также, как с дескрипторами сессии, их нужно просто переслать через сигнальный механизм. Если дескриптор сессии содержал информацию о наших установках на уровне камеры и микрофона, то кандидаты содержат информацию о нашем расположении в сети. Передайте их другому узлу, и тот сможет физически соединиться с нами, а так как у него уже есть и дескриптор сессии, то и логически сможет соединиться и данные «потекут». Если он не забудет отправить нам и свой объект кандидата, то есть информацию о том, где находится он сам в сети, то и мы сможем с ним соединиться. Заметим здесь еще одно отличие от классического клиент-серверного взаимодействия. Общение с HTTP сервером происходит по схеме запрос-ответ, клиент отправляет данные на сервер, тот обрабатывает их и шлет по адресу, указанному в пакете запроса . В WebRTC необходимо знать два адреса и соединять их с двух сторон.

    Различие от дескрипторов сессии состоит в том, что устанавливать нужно только удаленных кандидатов. Редактирование здесь запрещено и не может принести никакой пользы. В некоторых реализациях WebRTC кандидатов необходимо устанавливать только после установки дескрипторов сессии .

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

    Итак, два узла находятся в одной сети (Рисунок 8). Как их идентифицировать? С помощью IP адресов. Больше никак. Правда, еще можно использовать разные транспорты (TCP и UDP ) и разные порты. Это и есть та информация, которая содержится в объекте кандидата – IP , PORT , TRANSPORT и какая-то другая. Пусть, для примера, используется UDP транспорт и 531 порт.

    Рисунок 8: Два узла находятся в одной сети

    Тогда, если мы находимся в узле p1 , то WebRTC передаст нам такой объект кандидата - . Здесь приводится не точный формат, а лишь схема. Если мы в узле p2 , то кандидат таков – . Через сигнальный механизм p1 получит кандидата p2 (то есть расположение узла p2 , а именно его IP и PORT ). После чего p1 может соединиться с p2 напрямую. Более правильно, p1 будет посылать данные на адрес 10.50.150.3:531 в надежде, что они дойдут до p2 . Не важно, принадлежит ли этот адрес узлу p2 или какому-то посреднику. Важно лишь то, что через этот адрес данные будут посылаться и могут достигнуть p2 .

    Пока узлы в одной сети – все просто и легко – каждый узел имеет только один объект кандидата (всегда имеется в виду свой, то есть свое расположение в сети). Но кандидатов станет гораздо больше, когда узлы будут находится в разных сетях.

    Перейдем к более сложному случаю. Один узел будет находиться за роутером (точнее, за NAT), а второй узел будет находиться в одной сети с этим роутером (например, в интернете) (Рисунок 9).

    Рисунок 9: Один узел за NAT, другой нет

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

    Предположим, что веб-сервер соединен с интернетом напрямую, то есть имеет публичным IP * адрес. Пусть это будет узел p2 . Узел p1 (веб-клиент) шлет запрос на адрес 10.50.200.10 . Сначала данные попадают на роутер r1 , а точнее на его внутренний интерфейс 192.168.0.1 . После чего, роутер запоминает адрес источника (адрес p1 ) и заносит его в специальную таблицу NAT , затем изменяет адрес источника на свой(p1 → r1 ). Далее, по своему внешнему интерфейсу роутер пересылает данные непосредственно на веб‑сервер p2 . Веб-сервер обрабатывает данные, генерирует ответ и отправляет обратно. Отправляет роутеру r1 , так как именно он стоит в обратном адресе (роутер подменил адрес на свой). Роутер получает данные, смотрит в таблицу NAT и пересылает данные узлу p1 . Роутер выступает здесь как посредник.

    А что если несколько узлов из внутренней сети одновременно обращаются к внешней сети? Как роутер поймет кому отправлять ответ обратно? Эта проблема решается с помощью портов . Когда роутер подменяет адрес узла на свой, он также подменяет и порт. Если два узла обращаются к интернету, то роутер подменяет их порты источников на разные . Тогда, когда пакет от веб‑сервера придет обратно к роутеру, то роутер поймет по порту, кому назначен данный пакет. Пример ниже.

    Вернемся к технологии WebRTC , а точнее, к ее части, которая использует ICE протокол (отсюда и Ice кандидаты). Узел p2 имеет одного кандидата (свое расположение в сети – 10.50.200.10 ), а узел p1 , который находится за роутером с NAT, будет иметь двух кандидатов – локального (192.168.0.200 ) и кандидата роутера (10.50.200.5 ). Первый не пригодится, но он, тем не менее, генерируется, так как WebRTC еще ничего не знает об удаленном узле – он может находиться в той же сети, а может и нет. Второй кандидат пригодится, и, как мы уже знаем, важную роль будет играть порт (чтобы пройти через NAT ).

    Запись в таблице NAT генерируется только когда данные выходят из внутренней сети. Поэтому узел p1 должен первым передать данные и только после этого данные узла p2 смогут добраться до узла p1 .

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

    Однако, если внешние адреса известны, то соединение будет легко установлено. Если первый узел отошлет данные на роутер второго узла, то роутер их проигнорирует, так как его таблица NAT пока пуста. Однако в роутере первого узла в таблице NAT появилась нужна запись. Если теперь второй узел отправит данные на роутер первого узла, то роутер их успешно передаст первому узлу. Теперь и таблица NAT второго роутера имеет нужны данные.

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

    STUN и TURN сервера

    При инициализации WebRTC необходимо указать доступные STUN и TURN сервера, которые мы в дальнейшем будем называть ICE серверами. Если сервера не будут указаны, то соединиться смогут только узлы в одной сети (подключенные к ней без NAT ). Сразу стоит отметить, что для 3g -сетей обязательно использование TURN серверов.

    STUN сервер – это просто сервер в интернете, который возвращает обратный адрес, то есть адрес узла отправителя. Узел, находящий за роутером, обращается к STUN серверу, чтобы пройти через NAT . Пакет, пришедший к STUN серверу, содержит адрес источника – адрес роутера, то есть внешний адрес нашего узла. Этот адрес STUN сервер и отправляет обратно. Таким образом, узел получает свой внешний IP адрес и порт, через который он доступен из сети. Далее, WebRTC с помощью этого адреса создает дополнительного кандидата (внешний адрес роутера и порт). Теперь в таблице NAT роутера есть запись, которая пропускает к нашему узлу пакеты, отправленные на роутер по нужному порту.

    Рассмотрим этот процесс на примере.

    Пример (работа STUN сервера)

    STUN сервер будем обозначать через s1 . Роутер, как и раньше, через r1 , а узел – через p1 . Также необходимо будет следить за таблицей NAT – ее обозначим как r1_nat . Причем в этой таблице обычно содержится много записей от разный узлов подсети – они приводиться не будут.

    Итак, в начале имеем пустую таблицу r1_nat .

    Таблица 2: Заголовок пакета

    Узел p1 отправляет этот пакет роутеру r1 (не важно каким образом, в разных подсетях могут быть использованы разные технологии). Роутеру необходимо сделать подмену адреса источника Src IP , так как указанный в пакете адрес заведомо не подойдет для внешней подсети, более того, адреса из такого диапазона зарезервированы, и ни один адрес в интернете не имеет такого адреса. Роутер делает подмену в пакете и создает новую запись в своей таблице r1_nat . Для этого ему нужно придумать номер порта. Напомним, что, так как несколько узлов внутри подсети могут обращаться к внешней сети, то в таблице NAT должна храниться дополнительная информация, чтобы роутер смог определить, кому из этих нескольких узлов предназначается обратный пакет от сервера. Пусть роутер придумал порт 888 .

    Измененный заголовок пакета:

    Таблица 4: Таблица NAT пополнилась новой записью

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

    Настоящий порт, на который узел p1 принимает подключение – это, разумеется, 35777 , но сервер шлет данные на фиктивный порт 888 , который будет изменен роутером на настоящий 35777 .

    Итак, роутер подменил адрес и порт источника в заголовке пакета и добавил запись в таблицу NAT . Теперь пакет отправляется по сети серверу, то есть узлу s1 . На входе, s1 имеет такой пакет:

    Src IP Src PORT Dest IP Dest PORT
    10.50.200.5 888 12.62.100.200 6000

    Таблица 5: STUN сервер получил пакет

    Итого, STUN сервер знает, что ему пришел пакет от адреса 10.50.200.5:888 . Теперь этот адрес сервер отправляет обратно. Здесь стоит остановиться и еще раз посмотреть, что мы только что рассматривали. Таблицы, приведенные выше – это кусочек из заголовка пакета, вовсе не из его содержимого . О содержимом мы не говорили, так как это не столь важно – оно как-то описывается в протоколе STUN . Теперь же мы будем рассматривать помимо заголовка еще и содержимое. Оно будет простым и содержать адрес роутера – 10.50.200.5:888 , хотя взяли мы его из заголовка пакета. Такое делается не часто, обычно протоколам не важна информация об адресах узлов, важно лишь, чтобы пакеты доставлялись по назначению. Здесь же мы рассматриваем протокол, который устанавливает путь между двумя узлами.

    Итак, теперь у нас появляется второй пакет, который идет в обратном направлении:

    Таблица 7: STUN сервер отправляет пакет с таким содержимым

    Далее, пакет путешествует по сети, пока не окажется на внешнем интерфейсе роутера r1 . Роутер понимает, что пакет предназначен не ему. Как он это понимает? Это можно узнать только по порту. Порт 888 он не использует для своих личных целей, а использует для механизма NAT . Поэтому в эту таблицу роутер и смотрит. Смотрит на столбец External PORT и ищет строку, которая совпадет с Dest PORT из пришедшего пакета, то есть 888 .

    Internal IP Internal PORT External IP External PORT
    192.168.0.200 35777 10.50.200.5 888

    Таблица 8: Таблица NAT

    Нам повезло, такая строчка существует. Если бы не повезло, то пакет бы просто отбросился. Теперь нужно понять, кому из узлов подсети надо отправлять этот пакет. Не стоит торопиться, давайте снова вспомним о важности портов в этом механизме. Одновременно два узла в подсети могли бы отправлять запросы во внешнюю сеть. Тогда, если для первого узла роутер придумал порт 888 , то для второго он бы придумал порт 889 . Предположим, что так и случилось, то есть таблица r1_nat выглядит так:

    Таблица 10: Роутер подменяет адрес приемника

    Src IP Src PORT Dest IP Dest PORT
    12.62.100.200 6000 192.168.0.200 35777

    Таблица 11: Роутер подменил адрес приемника

    Пакет успешно приходит к узлу p1 и, посмотрев на содержимое пакета, узел узнает о своем внешнем IP адресе, то есть об адресе роутера во внешней сети. Также он знает и порт, который роутер пропускает через NAT .

    Что же дальше? Какая от этого всего польза? Польза – это запись в таблице r1_nat . Если теперь кто угодно будет отправлять на роутер r1 пакет с портом 888 , то роутер перенаправит этот пакет узлу p1 . Таким образом, создался небольшой узкий проход к спрятанному узлу p1 .

    Из примера выше можно получить некоторое представление о работе NAT и сути STUN сервера. Вообще, механизм ICE и STUN/TURN сервера как раз и направлены на преодоления ограничений NAT .

    Между узлом и сервером может стоять не один роутер, а несколько. В таком случае узел получит адрес того роутера, который является первым выходящим в ту же сеть, что и сервер. Иными словами, получим адрес роутера, подключенного к STUN серверу. Для p2p коммуникации это как раз то, что нам нужно, если не забыть тот факт, что в каждом роутере добавится необходимая нам строчка в таблицу NAT . Поэтому обратный путь будет вновь так же гладок.

    TURN сервер – это улучшенный STUN сервер. Отсюда сразу следует извлечь, что любой TURN сервер может работать и как STUN сервер. Однако, есть и преимущества. Если p2p коммуникация невозможна (как например, в 3g сетях), то сервер переходит в режим ретранслятора (relay ), то есть работает как посредник. Разумеется, ни о каком p2p тогда речь не идет, но за рамками механизма ICE узлы думают, что общаются напрямую.

    В каких случаях необходим TURN сервер? Почему не хватает STUN сервера? Дело в том, что существует несколько разновидностей NAT . Они одинаково подменяют IP адрес и порт, однако в некоторые из них встроена дополнительная защита от “фальсификации”. Например, в симметричной таблице NAT сохраняются еще 2 параметра - IP и порт удаленного узла. Пакет из внешней сети проходит через NAT во внутреннюю сеть только в том случае, если адрес и порт источника совпадают с записанными в таблице. Поэтому фокус со STUN сервером не удается - таблица NAT хранит адрес и порт STUN сервера и, когда роутер получает пакет от WebRTC собеседника, он его отбрасывает, так как он “фальсифицирован”. Он пришел не от STUN сервера.

    Таким образом TURN сервер нужен в том случае, когда оба собеседника находятся за симметричным NAT (каждый за своим).

    Краткая сводка

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

    • Медиа поток
      • Видео и аудио данные упаковываются в медиа потоки
      • Медиа потоки синхронизируют медиа дорожки, из которых состоят
      • Различные медиа потоки не синхронизированы между собой
      • Медиа потоки могут быть локальными и удаленными, к локальному обычно подключена камера и микрофон, удаленные получают данные из сети в кодированном виде
      • Медиа дорожки бывают двух типов – для видео и для аудио
      • Медиа дорожки имеют возможность включения/выключения
      • Медиа дорожки состоят из медиа каналов
      • Медиа дорожки синхронизируют медиа каналы, из которых состоят
      • Медиа потоки и медиа дорожки имеют метки, по которым их можно различать
    • Дескриптор сессии
      • Дескриптор сессии используется для логического соединения двух узлов сети
      • Дескриптор сессии хранит информацию о доступных способах кодирования видео и аудио данных
      • WebRTC использует внешний сигнальный механизм – задача пересылки дескрипторов сессии (sdp ) ложится на приложение
      • Механизм логического соединения состоит из двух этапов – предложения (offer ) и ответа (answer )
      • Генерация дескриптора сессии невозможна без использования локального медиа потока в случае предложения (offer ) и невозможна без использования удаленного дескриптора сессии в случае ответа (answer )
      • Полученный дескриптор надо отдать реализации WebRTC , причем неважно, получен ли этот дескриптор удаленно или же локально от той же реализации WebRTC
      • Имеется возможность небольшой правки дескриптора сессии
    • Кандидаты
      • Кандидат (Ice candidate ) – это адрес узла в сети
      • Адрес узла может быть своим, а может быть адресом роутера или TURN сервера
      • Кандидатов всегда много
      • Кандидат состоит из IP адреса, порта и типа транспорта (TCP или UDP )
      • Кандидаты используются для установления физического соединения двух узлов в сети
      • Кандидатов также нужно пересылать через сигнальный механизм
      • Кандидатов также нужно передавать реализации WebRTC , однако только удаленных
      • В некоторых реализациях WebRTC кандидатов можно передавать только после установки дескриптора сессии
    • STUN/TURN/ICE/NAT
      • NAT – механизм обеспечения доступа к внешней сети
      • Домашние роутеры поддерживают специальную таблицу NAT
      • Роутер подменяет адреса в пакетах – адрес источника на свой, в случае, если пакет идет во внешнюю сеть, и адрес приемника на адрес узла во внутренней сети, если пакет пришел из внешней сети
      • Для обеспечения многоканального доступа к внешней сети NAT использует порты
      • ICE – механизм обхода NAT
      • STUN и TURN сервера – сервера-помошники для обхода NAT
      • STUN сервер позволяет создавать необходимые записи в таблице NAT , а также возвращает внешний адрес узла
      • TURN сервер обобщает STUN механизм и делает его работающим всегда
      • В наихудших случаях TURN сервер используется как посредник (relay ), то есть p2p превращается в клиент-сервер-клиентную связь.