Создайте серверные службы, необходимые для приложения WebRTC.

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

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

  • Сообщения управления сеансом, используемые для открытия или закрытия связи.
  • Сообщения об ошибках
  • Метаданные мультимедиа, такие как кодеки, настройки кодека, пропускная способность и типы мультимедиа.
  • Ключевые данные, используемые для установления безопасных соединений
  • Сетевые данные, такие как IP-адрес и порт хоста, видимые из внешнего мира.

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

Почему сигнализация не определяется WebRTC?

Чтобы избежать избыточности и максимизировать совместимость с существующими технологиями, методы и протоколы сигнализации не указаны в стандартах WebRTC. Этот подход описан протоколом установления сеанса JavaScript (JSEP) :

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

Схема архитектуры JSEP
JSEP-архитектура

JSEP требует обмена между узлами предложения и ответа — медиа-метаданных, упомянутых выше. Предложения и ответы передаются в формате протокола описания сеанса (SDP), который выглядит следующим образом:

v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2

Хотите знать, что на самом деле означает вся эта чушь СДП? Взгляните на примеры IETF .

Имейте в виду, что WebRTC спроектирован таким образом, что предложение или ответ можно настроить перед тем, как они будут установлены в качестве локального или удаленного описания, путем редактирования значений в тексте SDP. Например, функцию preferAudioCodec() в appr.tc можно использовать для установки кодека и битрейта по умолчанию. SDP несколько болезненно манипулировать с помощью JavaScript, и ведутся дискуссии о том, должны ли будущие версии WebRTC вместо этого использовать JSON, но есть некоторые преимущества в использовании SDP.

API RTCPeerConnection и сигнализация: предложение, ответ и кандидат

RTCPeerConnection — это API, используемый приложениями WebRTC для создания соединения между узлами и передачи аудио и видео.

Чтобы инициализировать этот процесс, RTCPeerConnection выполняет две задачи:

  • Определите местные условия носителя, такие как разрешение и возможности кодека. Это метаданные, используемые для механизма предложений и ответов.
  • Получите потенциальные сетевые адреса хоста приложения, известные как кандидаты .

Как только эти локальные данные будут получены, ими необходимо обменяться через механизм сигнализации с удаленным узлом.

Представьте, что Алиса пытается позвонить Еве . Вот полный механизм предложения/ответа во всех его кровавых деталях:

  1. Алиса создает объект RTCPeerConnection .
  2. Алиса создает предложение (описание сеанса SDP) с помощью метода createOffer() RTCPeerConnection .
  3. Алиса вызывает setLocalDescription() со своим предложением.
  4. Алиса формулирует предложение и использует механизм сигнализации, чтобы отправить его Еве.
  5. Ева вызывает setRemoteDescription() с предложением Алисы, чтобы ее RTCPeerConnection знал о настройке Алисы.
  6. Ева вызывает createAnswer() , и в ответ на успешный вызов передается описание локального сеанса — ответ Евы.
  7. Ева устанавливает свой ответ как локальное описание, вызывая setLocalDescription() .
  8. Затем Ева использует механизм сигнализации, чтобы отправить свой строковый ответ Алисе.
  9. Алиса устанавливает ответ Евы в качестве описания удаленного сеанса с помощью setRemoteDescription() .

Алисе и Еве также необходимо обменяться сетевой информацией. Выражение «поиск кандидатов» относится к процессу поиска сетевых интерфейсов и портов с использованием фреймворка ICE .

  1. Алиса создает объект RTCPeerConnection с обработчиком onicecandidate .
  2. Обработчик вызывается, когда сетевые кандидаты становятся доступными.
  3. В обработчике Алиса отправляет Еве строковые данные-кандидаты через их сигнальный канал.
  4. Когда Ева получает сообщение о кандидате от Алисы, она вызывает addIceCandidate() чтобы добавить кандидата в описание удаленного узла.

JSEP поддерживает ICE Candidate Trickling , что позволяет вызывающему абоненту постепенно предоставлять кандидатов вызываемому абоненту после первоначального предложения, а вызываемый абонент может начать действовать по вызову и установить соединение, не дожидаясь прибытия всех кандидатов.

Код WebRTC для сигнализации

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

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // send the offer to the other peer
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

Чтобы увидеть процессы предложения/ответа и обмена кандидатами в действии, посетите сайт simpl.info RTCPeerConnection и посмотрите в журнале консоли пример одностраничного видеочата. Если вам нужно больше, загрузите полный дамп сигналов и статистики WebRTC со страницы about://webrtc-internals в Google Chrome или страницы Opera://webrtc-internals в Opera.

Одноранговое открытие

Это необычный способ спросить: «Как мне найти кого-нибудь, с кем можно поговорить?»

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

Механизмы обнаружения одноранговых узлов не определяются WebRTC, и здесь вы не вдаваетесь в параметры. Этот процесс может быть таким же простым, как отправка URL-адреса по электронной почте или сообщением. В приложениях для видеочата, таких как Talky , tawk.to и Browser Meeting , вы приглашаете людей на звонок, делясь специальной ссылкой. Разработчик Крис Болл создал интригующий эксперимент с бессерверным WebRTC , который позволяет участникам вызовов WebRTC обмениваться метаданными с помощью любой службы обмена сообщениями, которая им нравится, например, IM, электронная почта или почтовый голубь.

Как создать службу сигнализации?

Еще раз повторю: протоколы и механизмы сигнализации не определены стандартами WebRTC. Что бы вы ни выбрали, вам понадобится промежуточный сервер для обмена сигнальными сообщениями и данными приложений между клиентами. К сожалению, веб-приложение не может просто кричать в Интернет: «Соедините меня с моим другом!»

К счастью, сигнальные сообщения невелики и в основном передаются в начале вызова. При тестировании сеанса видеочата с помощью appr.tc служба сигнализации обработала в общей сложности около 30–45 сообщений с общим размером всех сообщений около 10 КБ.

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

Отправка сообщений с сервера клиенту

Служба сообщений для сигнализации должна быть двунаправленной: клиент-сервер и сервер-клиент. Двунаправленная связь противоречит модели запроса/ответа HTTP клиент/сервер, но на протяжении многих лет были разработаны различные хаки, такие как длительный опрос , для передачи данных из службы, работающей на веб-сервере, в веб-приложение, работающее в браузере.

Совсем недавно широкое распространение получил EventSource API . Это позволяет отправлять события, отправляемые сервером, — данные, отправляемые с веб-сервера клиенту браузера через HTTP. EventSource предназначен для одностороннего обмена сообщениями, но его можно использовать в сочетании с XHR для создания службы обмена сигнальными сообщениями. Служба сигнализации передает сообщение от вызывающего абонента, доставленное по запросу XHR, направляя его через EventSource вызываемому абоненту.

WebSocket — более естественное решение, предназначенное для полнодуплексной связи клиент-сервер — сообщения могут передаваться в обоих направлениях одновременно. Одним из преимуществ службы сигнализации, созданной с использованием чистого WebSocket или событий, отправляемых сервером ( EventSource ), является то, что серверная часть для этих API может быть реализована на различных веб-платформах, общих для большинства пакетов веб-хостинга для таких языков, как PHP, Python и Руби.

Все современные браузеры, кроме Opera Mini, поддерживают WebSocket и, что более важно, все браузеры, поддерживающие WebRTC, также поддерживают WebSocket, как на настольных компьютерах, так и на мобильных устройствах. TLS следует использовать для всех соединений, чтобы гарантировать невозможность перехвата сообщений в незашифрованном виде, а также для уменьшения проблем с обходом прокси-сервера . (Дополнительную информацию о WebSocket и обходе прокси см. в главе WebRTC в книге Ильи Григорика «Высокопроизводительная браузерная сеть ».)

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

Масштабная сигнализация

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

  • eXtensible Messaging and Presence Protocol (XMPP), первоначально известный как Jabber — протокол, разработанный для обмена мгновенными сообщениями, который можно использовать для сигнализации (реализации сервера включают ejabberd и Openfire . Клиенты JavaScript, такие как Strope.js , используют BOSH для эмуляции двунаправленной потоковой передачи, но по разным причинам BOSH может быть не таким эффективным, как WebSocket, и по тем же причинам может плохо масштабироваться.) (На касательно, Jingle — это расширение XMPP, обеспечивающее передачу голоса и видео. Проект WebRTC использует сетевые и транспортные компоненты из библиотеки libjingle — реализации Jingle на C++.)

  • Библиотеки с открытым исходным кодом, такие как ZeroMQ (используемые TokBox для службы Rumor ) и OpenMQ ( NullMQ применяет концепции ZeroMQ к веб-платформам, используя протокол STOMP через WebSocket.)

  • Коммерческие платформы облачных сообщений, использующие WebSocket (хотя они могут прибегать к длинному опросу), такие как Pusher , Kaazing и PubNub (PubNub также имеет API для WebRTC ).

  • Коммерческие платформы WebRTC, такие как vLine.

( Руководство по веб-технологиям реального времени , написанное разработчиком Филом Леггеттером, содержит полный список служб и библиотек обмена сообщениями.)

Создайте службу сигнализации с помощью Socket.io на Node.

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

Socket.io использует WebSocket с резервными вариантами: длинный опрос AJAX, многочастная потоковая передача AJAX, Forever Iframe и опрос JSONP. Он был портирован на различные серверные части, но, пожалуй, наиболее известен своей версией Node, использованной в этом примере.

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

Вот клиентский index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC client</title>
  </head>
  <body>
    <script src='/socket.io/socket.io.js'></script>
    <script src='js/main.js'></script>
  </body>
</html>

Вот файл JavaScript main.js на который есть ссылка в клиенте:

const isInitiator;

room = prompt('Enter room name:');

const socket = io.connect();

if (room !== '') {
  console.log('Joining room ' + room);
  socket.emit('create or join', room);
}

socket.on('full', (room) => {
  console.log('Room ' + room + ' is full');
});

socket.on('empty', (room) => {
  isInitiator = true;
  console.log('Room ' + room + ' is empty');
});

socket.on('join', (room) => {
  console.log('Making request to join room ' + room);
  console.log('You are the initiator!');
});

socket.on('log', (array) => {
  console.log.apply(console, array);
});

Вот полное серверное приложение:

const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
  file.serve(req, res);
}).listen(2013);

const io = require('socket.io').listen(app);

io.sockets.on('connection', (socket) => {

  // Convenience function to log server messages to the client
  function log(){
    const array = ['>>> Message from server: '];
    for (const i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
      socket.emit('log', array);
  }

  socket.on('message', (message) => {
    log('Got message:', message);
    // For a real app, would be room only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', (room) => {
    const numClients = io.sockets.clients(room).length;

    log('Room ' + room + ' has ' + numClients + ' client(s)');
    log('Request to create or join room ' + room);

    if (numClients === 0){
      socket.join(room);
      socket.emit('created', room);
    } else if (numClients === 1) {
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room);
    } else { // max two clients
      socket.emit('full', room);
    }
    socket.emit('emit(): client ' + socket.id +
      ' joined room ' + room);
    socket.broadcast.emit('broadcast(): client ' + socket.id +
      ' joined room ' + room);

  });

});

(Для этого вам не нужно изучать Node-Static. Он просто используется в этом примере.)

Чтобы запустить это приложение на локальном хосте, вам необходимо установить Node, Socket.IO и node-static . Node можно загрузить с Node.js (установка проста и быстра). Чтобы установить Socket.IO и node-static, запустите Node Package Manager из терминала в каталоге вашего приложения:

npm install socket.io
npm install node-static

Чтобы запустить сервер, запустите следующую команду из терминала в каталоге вашего приложения:

node server.js

В браузере откройте localhost:2013 . Откройте новую вкладку или окно в любом браузере и снова откройте localhost:2013 . Чтобы увидеть, что происходит, проверьте консоль. В Chrome и Opera вы можете получить доступ к консоли через инструменты разработчика Google Chrome, нажав Ctrl+Shift+J (или Command+Option+J на Mac).

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

Сигнальные ошибки

  • RTCPeerConnection не начнет собирать кандидатов, пока не будет вызвана setLocalDescription() . Это предусмотрено проектом JSEP IETF .
  • Воспользуйтесь преимуществами Trickle ICE. Вызовите addIceCandidate() как только прибудут кандидаты.

Готовые серверы сигнализации

Если вы не хотите создавать свои собственные, есть несколько доступных серверов сигнализации WebRTC, которые используют Socket.IO, как в предыдущем примере, и интегрированы с клиентскими библиотеками JavaScript WebRTC:

  • webRTC.io — одна из первых библиотек абстракции для WebRTC.
  • Signalmaster — это сервер сигнализации, созданный для использования с клиентской библиотекой JavaScript SimpleWebRTC .

Если вы вообще не хотите писать какой-либо код, можно приобрести полноценные коммерческие платформы WebRTC от таких компаний, как vLine , OpenTok и Asterisk .

Для справки, Эрикссон создал сервер сигнализации с использованием PHP на Apache на заре WebRTC. Сейчас это несколько устарело, но стоит посмотреть код, если вы рассматриваете что-то подобное.

Безопасность сигнализации

«Безопасность — это искусство ничего не делать».

Салман Рушди

Шифрование является обязательным для всех компонентов WebRTC.

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

Важнейшим фактором защиты сигнализации является использование безопасных протоколов — HTTPS и WSS (например, TLS), которые гарантируют, что сообщения не могут быть перехвачены в незашифрованном виде. Кроме того, будьте осторожны, чтобы не транслировать сигнальные сообщения так, чтобы к ним могли получить доступ другие вызывающие абоненты, использующие тот же сервер сигнализации.

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

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

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

Простое одноранговое соединение
Мир без NAT и межсетевых экранов

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

Пиры за NAT и межсетевыми экранами
Реальный мир

Приложения WebRTC могут использовать платформу ICE для преодоления сложностей реальных сетей. Чтобы это произошло, ваше приложение должно передавать URL-адреса сервера ICE в RTCPeerConnection , как описано в этой статье.

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

Другими словами, сервер STUN используется для получения адреса внешней сети, а серверы TURN используются для ретрансляции трафика в случае сбоя прямого (однорангового) соединения.

Каждый сервер TURN поддерживает STUN. Сервер TURN — это сервер STUN с дополнительными встроенными функциями ретрансляции. ICE также справляется со сложностями настройки NAT. В действительности для пробивания отверстий NAT может потребоваться нечто большее, чем просто общедоступный IP-адрес порта.

URL-адреса для серверов STUN и/или TURN (необязательно) указываются приложением WebRTC в объекте конфигурации iceServers , который является первым аргументом конструктора RTCPeerConnection . Для appr.tc это значение выглядит следующим образом:

{
  'iceServers': [
    {
      'urls': 'stun:stun.l.google.com:19302'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

Как только RTCPeerConnection получит эту информацию, волшебство ICE произойдет автоматически. RTCPeerConnection использует структуру ICE для определения наилучшего пути между узлами, работая при необходимости с серверами STUN и TURN.

Оглушение

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

Серверы STUN находятся в общедоступном Интернете и имеют одну простую задачу — проверить адрес IP:port входящего запроса (из приложения, работающего за NAT) и отправить этот адрес обратно в качестве ответа. Другими словами, приложение использует STUN-сервер для обнаружения своего IP-порта с публичной точки зрения. Этот процесс позволяет узлу WebRTC получить общедоступный адрес для себя, а затем передать его другому узлу через механизм сигнализации для установки прямого соединения. (На практике разные NAT работают по-разному, и может существовать несколько уровней NAT, но принцип остается тем же.)

STUN-серверам не нужно много делать или много запоминать, поэтому STUN-серверы с относительно низкими характеристиками могут обрабатывать большое количество запросов.

Большинство вызовов WebRTC успешно устанавливают соединение с использованием STUN — 86% по данным Webrtcstats.com , хотя это может быть меньше для вызовов между узлами за брандмауэрами и сложными конфигурациями NAT.

Одноранговое соединение с использованием STUN-сервера
Использование серверов STUN для получения общедоступных IP-адресов портов

ПОВЕРНУТЬ

RTCPeerConnection пытается установить прямую связь между узлами через UDP. Если это не удается, RTCPeerConnection прибегает к TCP. Если это не поможет, серверы TURN можно использовать в качестве запасного варианта, передавая данные между конечными точками.

Еще раз повторю: TURN используется для ретрансляции потоков аудио, видео и данных между узлами, а не для передачи данных!

Серверы TURN имеют публичные адреса, поэтому узлы могут связаться с ними, даже если узлы находятся за брандмауэрами или прокси-серверами. У серверов TURN концептуально простая задача — ретранслировать поток. Однако, в отличие от серверов STUN, они по своей природе потребляют большую полосу пропускания. Другими словами, серверы TURN должны быть более мощными.

Одноранговое соединение с использованием STUN-сервера
Полный Монти: ОГЛУШЕНИЕ, ПОВОРОТ и подача сигналов.

На этой диаграмме показана функция ПОВОРОТ в действии. Использование чистого STUN не удалось, поэтому каждый узел прибегает к использованию сервера TURN.

Развертывание серверов STUN и TURN

Для тестирования Google запускает общедоступный сервер STUN stun.l.google.com:19302, используемый appr.tc. Для производственной службы STUN/TURN используйте сервер rfc5766-turn-server. Исходный код серверов STUN и TURN доступен на GitHub , там же можно найти ссылки на несколько источников информации об установке сервера. Также доступен образ виртуальной машины для Amazon Web Services .

Возобновлен альтернативный сервер TURN, доступный в виде исходного кода , а также для AWS. Ниже приведены инструкции по настройке возврата средств в Compute Engine.

  1. При необходимости откройте брандмауэр для tcp=443, udp/tcp=3478.
  2. Создайте четыре экземпляра, по одному для каждого общедоступного IP-адреса, стандартный образ Ubuntu 12.06.
  3. Настройте конфигурацию локального брандмауэра (разрешите ЛЮБОЙ из ЛЮБОГО).
  4. Инструменты установки: shell sudo apt-get install make sudo apt-get install gcc
  5. Установите libre с сайта creytiv.com/re.html .
  6. Получите возврат средств с сайта creytiv.com/restund.html и распакуйте./
  7. wget hancke.name/restund-auth.patch и примените patch -p1 < restund-auth.patch .
  8. Запустите make , sudo make install для libre и выполните возврат.
  9. Адаптируйте restund.conf к своим потребностям (замените IP-адреса и убедитесь, что он содержит тот же общий секретный ключ) и скопируйте его в /etc .
  10. Скопируйте restund/etc/restund в /etc/init.d/ .
  11. Настроить возврат:
    1. Установите LD_LIBRARY_PATH .
    2. Скопируйте restund.conf в /etc/restund.conf .
    3. Настройте restund.conf для использования правильного 10. IP-адреса.
  12. Запустить возврат
  13. Проверьте использование клиента stund с удаленного компьютера: ./client IP:port

Больше, чем общение один на один: Multiparty WebRTC

Вы также можете ознакомиться с предложенным Джастином Уберти стандартом IETF для REST API для доступа к службам TURN .

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

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

Сетка: небольшой N-сторонний вызов
Полноячеистая топология: все подключены ко всем.

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

Начиная с Chrome 31 и Opera 18, MediaStream из одного RTCPeerConnection может использоваться в качестве входных данных для другого. Это может обеспечить более гибкую архитектуру, поскольку позволяет веб-приложению обрабатывать маршрутизацию вызовов, выбирая, к какому другому узлу подключаться. Чтобы увидеть это в действии, см. примеры WebRTC Ретрансляция одноранговых соединений и примеры WebRTC с несколькими одноранговыми соединениями .

Многоточечный блок управления

Лучшим вариантом для большого количества конечных точек является использование Multipoint Control Unit (MCU). Это сервер, который работает как мост для распределения мультимедиа между большим количеством участников. MCU могут работать с различными разрешениями, кодеками и частотой кадров во время видеоконференции; обрабатывать транскодирование; выполнить выборочную пересылку потока; и микшировать или записывать аудио и видео. При многосторонних вызовах необходимо учитывать ряд проблем, в частности, как отображать несколько видеовходов и микшировать звук из нескольких источников. Облачные платформы, такие как vLine , также пытаются оптимизировать маршрутизацию трафика.

Можно купить полный аппаратный пакет MCU или собрать свой собственный.

Cisco MCU5300, вид сзади
Задняя часть Cisco MCU

Доступно несколько вариантов программного обеспечения MCU с открытым исходным кодом. Например, Licode (ранее известная как Lynckia) производит MCU с открытым исходным кодом для WebRTC. В OpenTok есть Mantis .

За пределами браузеров: VoIP, телефоны и обмен сообщениями

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

SIP — это протокол сигнализации, используемый системами VoIP и видеоконференцсвязи. Чтобы обеспечить связь между веб-приложением WebRTC и SIP-клиентом, например системой видеоконференций, WebRTC необходим прокси-сервер для передачи сигналов. Сигнализация должна проходить через шлюз, но после установления связи трафик SRTP (видео и аудио) может передаваться напрямую между узлами.

Коммутируемая телефонная сеть общего пользования (PSTN) — это сеть с коммутацией каналов всех «старых простых» аналоговых телефонов. Для вызовов между веб-приложениями WebRTC и телефонами трафик должен проходить через шлюз PSTN. Аналогично, веб-приложениям WebRTC необходим промежуточный сервер XMPP для связи с конечными точками Jingle , такими как IM-клиенты. Jingle был разработан Google как расширение XMPP для поддержки передачи голоса и видео в службах обмена сообщениями. Текущие реализации WebRTC основаны на библиотеке C++ libjingle , реализации Jingle, изначально разработанной для Talk.

Ряд приложений, библиотек и платформ используют возможности WebRTC для связи с внешним миром:

  • sipML5 : SIP-клиент JavaScript с открытым исходным кодом.
  • jsSIP : библиотека SIP JavaScript.
  • Phono : API телефона на JavaScript с открытым исходным кодом, созданный в виде плагина.
  • Zingaya : встраиваемый виджет телефона
  • Twilio : голос и обмен сообщениями
  • Уберконференция : конференц-связь

Разработчики sipML5 также создали шлюз webrtc2sip . Tethr и Tropo продемонстрировали структуру для экстренной связи «в портфеле» с использованием соты OpenBTS для обеспечения связи между функциональными телефонами и компьютерами через WebRTC. Это телефонная связь без оператора связи!

Узнать больше

Лаборатория кода WebRTC предоставляет пошаговые инструкции по созданию приложения для видео- и текстового чата с использованием службы сигнализации Socket.io, работающей на Node.

Презентация Google I/O WebRTC 2013 года с техническим руководителем WebRTC Джастином Уберти

Презентация Криса Уилсона SFHTML5 — Введение в приложения WebRTC

350-страничная книга WebRTC: API и протоколы RTCWEB в сети HTML5 реального времени содержит много подробностей о путях передачи данных и сигналов, а также включает ряд подробных диаграмм топологии сети.

WebRTC и сигнализация: чему нас научили два года — сообщение в блоге TokBox о том, почему исключение сигнализации из спецификации было хорошей идеей

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

Глава WebRTC в книге Ильи Григорика «Высокопроизводительная браузерная сеть» подробно рассматривает архитектуру WebRTC, варианты использования и производительность.