خدمات پشتیبانی مورد نیاز برای یک برنامه WebRTC را بسازید

سیگنالینگ چیست؟

سیگنالینگ فرآیند هماهنگی ارتباطات است. برای اینکه یک برنامه WebRTC تماس برقرار کند، مشتریان آن باید اطلاعات زیر را مبادله کنند:

  • پیام‌های کنترل جلسه که برای باز کردن یا بستن ارتباطات استفاده می‌شوند
  • پیغام خطا
  • فراداده رسانه، مانند کدک ها، تنظیمات کدک، پهنای باند و انواع رسانه
  • داده های کلیدی مورد استفاده برای ایجاد اتصالات ایمن
  • داده‌های شبکه، مانند آدرس IP و پورت میزبان که توسط دنیای خارج مشاهده می‌شود

این فرآیند سیگنالینگ به روشی نیاز دارد تا مشتریان بتوانند پیام ها را به عقب و جلو منتقل کنند. این مکانیسم توسط WebRTC API ها اجرا نمی شود. شما باید خودتان آن را بسازید. در ادامه این مقاله، راه های ساخت یک سرویس سیگنالینگ را یاد می گیرید. با این حال، ابتدا به یک زمینه کوچک نیاز دارید.

چرا سیگنالینگ توسط WebRTC تعریف نشده است؟

برای جلوگیری از افزونگی و به حداکثر رساندن سازگاری با فناوری های موجود، روش ها و پروتکل های سیگنالینگ توسط استانداردهای WebRTC مشخص نشده اند. این رویکرد توسط پروتکل استقرار جلسه جاوا اسکریپت (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
…

آیا می خواهید بدانید که این همه SDP gobbledygook واقعاً به چه معناست؟ نگاهی به نمونه های کارگروه مهندسی اینترنت (IETF) بیندازید.

به خاطر داشته باشید که WebRTC طوری طراحی شده است که پیشنهاد یا پاسخ را می توان قبل از تنظیم به عنوان توضیحات محلی یا راه دور با ویرایش مقادیر در متن SDP تغییر داد. به عنوان مثال، تابع preferAudioCodec() در appr.tc می تواند برای تنظیم کدک و میزان بیت پیش فرض استفاده شود. دستکاری SDP با جاوا اسکریپت تا حدودی دردناک است و در مورد اینکه آیا نسخه های آینده WebRTC باید به جای آن از JSON استفاده کنند یا خیر، بحث وجود دارد، اما استفاده از SDP مزایایی دارد.

RTCPeerConnection API و سیگنالینگ: پیشنهاد، پاسخ و نامزد

RTCPeerConnection API است که توسط برنامه های WebRTC برای ایجاد ارتباط بین همتایان و برقراری ارتباط صوتی و تصویری استفاده می شود.

برای مقداردهی اولیه این فرآیند، RTCPeerConnection دو وظیفه دارد:

  • شرایط رسانه محلی، مانند قابلیت وضوح و کدک را بررسی کنید. این ابرداده مورد استفاده برای مکانیسم پیشنهاد و پاسخ است.
  • آدرس‌های شبکه احتمالی را برای میزبان برنامه، که به عنوان نامزد شناخته می‌شود، دریافت کنید.

هنگامی که این داده محلی مشخص شد، باید از طریق یک مکانیسم سیگنالینگ با همتای راه دور مبادله شود.

تصور کنید آلیس سعی می کند حوا را صدا کند . در اینجا مکانیسم پیشنهاد/پاسخ کامل با تمام جزییات وحشتناک آن آمده است:

  1. آلیس یک شی RTCPeerConnection ایجاد می کند.
  2. آلیس یک پیشنهاد (توضیح جلسه SDP) با متد RTCPeerConnection createOffer() ایجاد می کند.
  3. آلیس با پیشنهاد خود setLocalDescription() را فراخوانی می کند.
  4. آلیس پیشنهاد را محدود می کند و از مکانیزم سیگنالینگ برای ارسال آن به حوا استفاده می کند.
  5. ایو با پیشنهاد آلیس، setRemoteDescription() را فراخوانی می کند تا RTCPeerConnection او از تنظیمات آلیس مطلع شود.
  6. Eve 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 این گزینه را با برخی بهینه‌سازی‌ها برای فرکانس نظرسنجی انجام می‌دهد.

سیگنالینگ مقیاس

اگرچه یک سرویس سیگنالینگ پهنای باند و CPU نسبتا کمی را به ازای هر کلاینت مصرف می کند، سرورهای سیگنالینگ برای یک برنامه محبوب ممکن است مجبور شوند پیام های زیادی را از مکان های مختلف با سطح همزمانی بالا مدیریت کنند. برنامه های WebRTC که ترافیک زیادی دریافت می کنند به سرورهای سیگنالینگ نیاز دارند که بتوانند بار قابل توجهی را مدیریت کنند. در اینجا وارد جزئیات نمی‌شوید، اما تعدادی گزینه برای پیام‌رسانی با حجم بالا و عملکرد بالا وجود دارد، از جمله موارد زیر:

  • پروتکل پیام‌رسانی و حضور توسعه‌یافته (XMPP)، که در ابتدا با نام Jabber شناخته می‌شد، پروتکلی است که برای پیام‌رسانی فوری توسعه یافته و می‌تواند برای سیگنال‌دهی استفاده شود (اجراهای سرور شامل ejabberd و Openfire هستند. مشتریان جاوا اسکریپت، مانند Strophe.js ، از BOSH برای شبیه‌سازی جریان دوطرفه استفاده می‌کنند. اما به دلایل مختلف ، BOSH ممکن است به اندازه WebSocket کارآمد نباشد و به همان دلایل، ممکن است به خوبی مقیاس نشود.) (در یک مماس، Jingle یک پسوند XMPP برای فعال کردن صدا و تصویر است. پروژه WebRTC از اجزای شبکه و انتقال استفاده می کند. از کتابخانه libjingle - یک پیاده سازی C++ از Jingle.)

  • کتابخانه‌های منبع باز، مانند 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>

فایل جاوا اسکریپت 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 دوباره باز کنید. برای اینکه ببینید چه اتفاقی می افتد، کنسول را بررسی کنید. در کروم و اپرا، می‌توانید از طریق ابزارهای توسعه‌دهنده Google Chrome با Ctrl+Shift+J (یا Command+Option+J در مک) به کنسول دسترسی داشته باشید.

هر رویکردی را که برای سیگنالینگ انتخاب کنید، برنامه باطن و مشتری شما - حداقل - نیاز به ارائه خدمات مشابه این مثال دارد.

سیگنالینگ گوچاها

  • تا زمانی که setLocalDescription() فراخوانی نشود، RTCPeerConnection جمع آوری نامزدها را شروع نمی کند. این در پیش نویس JSEP IETF الزامی شده است.
  • از Trickle ICE بهره ببرید. به محض ورود نامزدها با addIceCandidate() تماس بگیرید.

سرورهای سیگنالینگ آماده

اگر نمی‌خواهید سرورهای خود را رول کنید، چندین سرور سیگنالینگ WebRTC در دسترس هستند که مانند مثال قبلی از Socket.IO استفاده می‌کنند و با کتابخانه‌های JavaScript کلاینت WebRTC یکپارچه شده‌اند:

  • webRTC.io یکی از اولین کتابخانه های انتزاعی برای WebRTC است.
  • Signalmaster یک سرور سیگنالینگ است که برای استفاده با کتابخانه مشتری جاوا اسکریپت SimpleWebRTC ایجاد شده است.

اگر اصلاً نمی‌خواهید هیچ کدی بنویسید، پلتفرم‌های تجاری WebRTC کامل از شرکت‌هایی مانند vLine ، OpenTok و Asterisk در دسترس هستند.

برای ثبت، اریکسون یک سرور سیگنالینگ با استفاده از PHP در آپاچی در روزهای اولیه 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 عمومی: پورت نیاز داشته باشد.

نشانی‌های وب برای سرورهای 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 کار می کند.

STUN

NAT ها دستگاهی با یک آدرس IP برای استفاده در یک شبکه محلی خصوصی ارائه می دهند، اما این آدرس نمی تواند به صورت خارجی استفاده شود. بدون آدرس عمومی، هیچ راهی برای همتایان WebRTC برای ارتباط وجود ندارد. برای حل این مشکل، WebRTC از STUN استفاده می کند.

سرورهای STUN در اینترنت عمومی زندگی می کنند و یک کار ساده دارند - آدرس IP:پورت درخواست ورودی (از برنامه ای که پشت NAT اجرا می شود) را بررسی کنید و آن آدرس را به عنوان پاسخ ارسال کنید. به عبارت دیگر، برنامه از یک سرور STUN برای کشف IP:پورت خود از دیدگاه عمومی استفاده می کند. این فرآیند یک همتای WebRTC را قادر می‌سازد تا یک آدرس در دسترس عموم را برای خود دریافت کند و سپس آن را از طریق مکانیزم سیگنالینگ به همتای دیگر ارسال کند تا یک پیوند مستقیم را تنظیم کند. (در عمل، NAT های مختلف به روش های مختلف کار می کنند و ممکن است چندین لایه NAT وجود داشته باشد، اما اصل همچنان یکسان است.)

سرورهای STUN مجبور نیستند کارهای زیادی انجام دهند یا چیزهای زیادی را به خاطر بسپارند، بنابراین سرورهای STUN با مشخصات نسبتاً پایین می توانند تعداد زیادی از درخواست ها را انجام دهند.

طبق Webrtcstats.com ، اکثر تماس‌های WebRTC با استفاده از STUN - 86% با موفقیت ارتباط برقرار می‌کنند، اگرچه این ممکن است برای تماس‌های بین همتایان پشت فایروال و پیکربندی‌های پیچیده NAT کمتر باشد.

اتصال همتا به همتا با استفاده از سرور STUN
استفاده از سرورهای STUN برای دریافت آدرس های IP عمومی: پورت

دور زدن

RTCPeerConnection سعی می کند ارتباط مستقیم بین همتایان را از طریق UDP برقرار کند. اگر این کار انجام نشد، RTCPeerConnection به TCP متوسل می شود. اگر این کار انجام نشد، سرورهای TURN را می‌توان به‌عنوان یک بک گراند استفاده کرد و داده‌ها را بین نقاط پایانی انتقال می‌دهد.

فقط برای تکرار، TURN برای انتقال صدا، ویدئو، و جریان داده بین همتایان استفاده می شود، نه سیگنال دادن به داده ها!

سرورهای TURN دارای آدرس‌های عمومی هستند، بنابراین همتایان می‌توانند با آنها تماس بگیرند، حتی اگر همتایان پشت فایروال یا پراکسی باشند. سرورهای TURN از نظر مفهومی یک کار ساده دارند - انتقال یک جریان. با این حال، بر خلاف سرورهای STUN، آنها ذاتاً پهنای باند زیادی مصرف می کنند. به عبارت دیگر، سرورهای TURN باید قوی تر باشند.

اتصال همتا به همتا با استفاده از سرور STUN
مونتی کامل: STUN، TURN، و سیگنالینگ

این نمودار چرخش را در عمل نشان می دهد. Pure STUN موفق نشد، بنابراین هر همتا به استفاده از سرور TURN متوسل می شود.

استقرار سرورهای STUN و TURN

برای آزمایش، Google یک سرور STUN عمومی، stun.l.google.com:19302 را اجرا می کند که توسط appr.tc استفاده می شود. برای سرویس STUN/TURN تولیدی، از سرور rfc5766-turn-server استفاده کنید. کد منبع برای سرورهای STUN و TURN در GitHub موجود است، جایی که می‌توانید پیوندهایی به چندین منبع اطلاعاتی درباره نصب سرور پیدا کنید. یک تصویر VM برای خدمات وب آمازون نیز موجود است.

یک سرور جایگزین TURN restund است که به عنوان کد منبع و همچنین برای AWS موجود است. در اینجا دستورالعمل هایی برای نحوه تنظیم restund در Compute Engine آورده شده است.

  1. فایروال را در صورت لزوم برای tcp=443، udp/tcp=3478 باز کنید.
  2. چهار نمونه، یکی برای هر IP عمومی، تصویر استاندارد اوبونتو 12.06 ایجاد کنید.
  3. پیکربندی فایروال محلی را تنظیم کنید (به ANY از ANY اجازه دهید).
  4. ابزارهای نصب: shell sudo apt-get install make sudo apt-get install gcc
  5. Libre را از creytiv.com/re.html نصب کنید.
  6. restund را از creytiv.com/restund.html واکشی کنید و بسته را باز کنید./
  7. wget hancke.name/restund-auth.patch و با patch -p1 < restund-auth.patch اعمال کنید.
  8. make , sudo make install برای libre و restund اجرا کنید.
  9. restund.conf با نیازهای خود تطبیق دهید (آدرس های IP را جایگزین کنید و مطمئن شوید که حاوی همان راز مشترک است) و در /etc کپی کنید.
  10. restund/etc/restund در /etc/init.d/ کپی کنید.
  11. پیکربندی restund:
    1. LD_LIBRARY_PATH را تنظیم کنید.
    2. restund.conf در /etc/restund.conf کپی کنید.
    3. restund.conf برای استفاده از آدرس IP مناسب تنظیم کنید.
  12. restund را اجرا کنید
  13. تست با استفاده از Stand Client از دستگاه راه دور: ./client IP:port

فراتر از یک به یک: WebRTC چند حزبی

همچنین ممکن است بخواهید نگاهی به استاندارد IETF پیشنهادی جاستین اوبرتی برای REST API برای دسترسی به خدمات TURN بیندازید.

تصور موارد استفاده برای پخش رسانه ای که فراتر از یک تماس ساده یک به یک است، آسان است. برای مثال، کنفرانس ویدیویی بین گروهی از همکاران یا یک رویداد عمومی با یک سخنران و صدها یا میلیون ها بیننده.

یک برنامه WebRTC می تواند از چندین RTCPeerConnection استفاده کند تا هر نقطه پایانی در یک پیکربندی مش به هر نقطه پایانی دیگری متصل شود. این رویکردی است که توسط برنامه هایی مانند talky.io اتخاذ می شود و برای تعداد کمی از همتایان به خوبی کار می کند. فراتر از آن، پردازش و مصرف پهنای باند بیش از حد می شود، به ویژه برای مشتریان تلفن همراه.

مش: تماس کوچک N-way
توپولوژی مش کامل: همه به همه متصل هستند

از طرف دیگر، یک برنامه WebRTC می‌تواند یک نقطه پایانی را برای توزیع جریان‌ها به بقیه در یک پیکربندی ستاره انتخاب کند. همچنین می‌توان یک نقطه پایانی WebRTC را روی سرور اجرا کرد و مکانیزم توزیع مجدد خود را ساخت ( نمونه برنامه مشتری توسط webrtc.org ارائه شده است).

از Chrome 31 و Opera 18، MediaStream از یک RTCPeerConnection می تواند به عنوان ورودی برای دیگری استفاده شود. این می‌تواند معماری‌های انعطاف‌پذیرتری را فعال کند، زیرا یک برنامه وب را قادر می‌سازد تا با انتخاب همتای دیگری که باید به آن متصل شود، مسیریابی تماس را مدیریت کند. برای مشاهده عملی این، به نمونه‌های WebRTC رله اتصال همتا و نمونه‌های WebRTC اتصالات چندگانه همتا را ببینید.

واحد کنترل چند نقطه

یک گزینه بهتر برای تعداد زیادی از نقاط پایانی استفاده از واحد کنترل چند نقطه ای (MCU) است. این سروری است که به عنوان پلی برای توزیع رسانه بین تعداد زیادی از شرکت کنندگان عمل می کند. MCU ها می توانند با رزولوشن ها، کدک ها و نرخ فریم های مختلف در یک کنفرانس ویدئویی کنار بیایند. پردازش رمزگذاری ارسال انتخابی جریان را انجام دهید. و میکس یا ضبط صدا و تصویر. برای تماس‌های چند طرفه، مسائلی وجود دارد که باید در نظر گرفته شوند، به‌ویژه نحوه نمایش ورودی‌های ویدیوی متعدد و ترکیب صدا از چندین منبع. پلتفرم‌های ابری مانند vLine نیز تلاش می‌کنند تا مسیریابی ترافیک را بهینه کنند.

این امکان وجود دارد که یک بسته سخت افزاری کامل MCU بخرید یا خودتان بسازید.

نمای عقب سیسکو MCU5300
پشت 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 توسط گوگل به عنوان یک افزونه برای XMPP برای فعال کردن صدا و ویدئو برای خدمات پیام‌رسانی توسعه داده شد. پیاده‌سازی‌های کنونی WebRTC بر اساس کتابخانه C++ libjingle ، یک پیاده‌سازی از Jingle است که در ابتدا برای Talk توسعه داده شد.

تعدادی از برنامه ها، کتابخانه ها و پلتفرم ها از توانایی WebRTC برای برقراری ارتباط با دنیای خارج استفاده می کنند:

  • sipML5 : یک سرویس گیرنده SIP جاوا اسکریپت منبع باز
  • jsSIP : کتابخانه SIP جاوا اسکریپت
  • Phono : API تلفن منبع باز جاوا اسکریپت که به عنوان یک افزونه ساخته شده است
  • Zingaya : یک ویجت تلفن قابل جاسازی
  • Twilio : صدا و پیام
  • Uberconference : کنفرانس

توسعه دهندگان sipML5 دروازه webrtc2sip را نیز ساخته اند. Tethr و Tropo چارچوبی را برای ارتباطات فاجعه آمیز "در یک کیف" با استفاده از سلول OpenBTS برای فعال کردن ارتباطات بین تلفن های ویژه و رایانه ها از طریق WebRTC نشان داده اند. یعنی ارتباط تلفنی بدون اپراتور!

اطلاعات بیشتر

کد لبه WebRTC دستورالعمل های گام به گام را برای نحوه ساخت یک برنامه چت ویدیویی و متنی با استفاده از یک سرویس سیگنالینگ Socket.io که در Node اجرا می شود ارائه می دهد.

ارائه Google I/O WebRTC از سال 2013 با مدیر فناوری WebRTC، جاستین اوبرتی

ارائه SFHTML5 کریس ویلسون - مقدمه ای بر برنامه های WebRTC

کتاب 350 صفحه ای WebRTC: APIs و RTCWEB Protocols of the HTML5 Real-Time Web جزئیات زیادی در مورد داده ها و مسیرهای سیگنالینگ ارائه می دهد و شامل تعدادی نمودار توپولوژی شبکه دقیق است.

WebRTC و سیگنالینگ: آنچه دو سال به ما آموخت - پست وبلاگ TokBox در مورد اینکه چرا سیگنالینگ را خارج از مشخصات فنی گذاشتیم ایده خوبی بود

راهنمای عملی ساخت برنامه های WebRTC از بن استرانگ اطلاعات زیادی در مورد توپولوژی ها و زیرساخت های WebRTC ارائه می دهد.

فصل WebRTC در شبکه‌سازی مرورگر با کارایی بالا ایلیا گریگوریک به عمق معماری WebRTC، موارد استفاده و عملکرد می‌پردازد.