-
Notifications
You must be signed in to change notification settings - Fork 9
/
module-rtc-signaller.html
245 lines (227 loc) · 19.4 KB
/
module-rtc-signaller.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<title>rtc.io</title>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<!-- responsive -->
<link rel="stylesheet" media="screen and (max-width: 960px)" href="css/tablet.css">
<link rel="stylesheet" media="screen and (max-width: 710px)" href="css/phone.css">
<link rel="stylesheet" type="text/css" href="fonts/source-sans/stylesheet.css">
<link rel="stylesheet" type="text/css" href="css/code.css">
</head>
<body>
<a class="scroll-point pt-top" name="top"></a>
<header>
<a href="https://github.com/rtc-io/rtc-signaller"><img class="fork" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
<a class="scroll-point pt-top" name="top"></a>
<div class="site">
<div class="mascot">
<img src="images/artsio.png">
</div>
<div class="logo" data-subtext="OpenSource WebRTC">
<a href="index.html">rtc.io</a>
</div>
<nav>
<ul>
<li><a href="index.html">About</a></li>
<li><a href="tutorials.html">Tutorials</a></li>
<li><a href="demos.html">Demos</a></li>
<li><a href="modules.html">Modules</a></li>
</ul>
</nav>
</div>
<div class="shadow"></div>
</header>
<div class="main" role="content"><h1 id="rtc-signaller">rtc-signaller</h1>
<p>The <code>rtc-signaller</code> module provides a transportless signalling
mechanism for WebRTC.</p>
<p><a href="https://nodei.co/npm/rtc-signaller/"><img src="https://nodei.co/npm/rtc-signaller.png" alt="NPM"></a></p>
<p><a href="https://travis-ci.org/rtc-io/rtc-signaller"><img src="https://img.shields.io/travis/rtc-io/rtc-signaller.svg?branch=master" alt="Build Status"></a> <a href="https://github.com/dominictarr/stability#stable"><img src="https://img.shields.io/badge/stability-stable-green.svg" alt="stable"></a>
<a href="https://gitter.im/rtc-io"><img src="https://badges.gitter.im/rtc-io.png" alt="Gitter chat"></a></p>
<h2 id="purpose">Purpose</h2>
<p>The signaller provides set of client-side tools that assist with the setting up an <code>PeerConnection</code> and helping them communicate. All that is required for the signaller to operate is a <a href="https://github.com/DamonOehlman/messenger-archetype">suitable messenger</a>. A messenger is simply a function that is able to create a <a href="https://github.com/dominictarr/pull-stream">pull-stream</a> <code>Source</code> and/or <code>Sink</code>. From version <code>5.0.0</code> the <code>rtc-signaller</code> package will use pull-streams to ensure robust delivery of messages.</p>
<p>By using this approach, we can conduct signalling over any number of mechanisms:</p>
<ul>
<li>local, <a href="https://github.com/DamonOehlman/messenger-memory">in memory</a> message passing</li>
<li>via <a href="https://github.com/DamonOehlman/messenger-ws">WebSockets</a> and higher level abstractions (such as <a href="https://github.com/primus/primus">primus</a>)</li>
</ul>
<p>In the event that you want to implement a signaller without using pull-streams, then you can work from a base signaller using the <a href="https://github.com/rtc-io/rtc-signal/blob/master/signaller.js"><code>rtc-signal/signaller</code></a> implementation.</p>
<h2 id="getting-started">Getting Started</h2>
<p>While the signaller is capable of communicating by a number of different
messengers (i.e. anything that can send and receive messages over a wire)
it comes with support for understanding how to connect to an
<a href="https://github.com/rtc-io/rtc-switchboard">rtc-switchboard</a> out of the box.</p>
<p>The following code sample demonstrates how:</p>
<div class="highlight"><pre><span class="c1">// create a new signaller, connecting to the target switchboard</span>
<span class="kd">var</span> <span class="nx">messenger</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'rtc-switchboard-messenger'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">signaller</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'rtc-signaller'</span><span class="p">)(</span><span class="nx">messenger</span><span class="p">(</span><span class="s1">'//switchboard.rtc.io/'</span><span class="p">));</span>
<span class="c1">// when a new peer is announced, log it</span>
<span class="nx">signaller</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'peer:announce'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'new peer found in room: '</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// for our sanity, pop a message once we are connected</span>
<span class="nx">signaller</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s1">'connected'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'we have successfully connected'</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// send through an announce message</span>
<span class="c1">// this will occur once the websocket has been opened and active</span>
<span class="nx">signaller</span><span class="p">.</span><span class="nx">announce</span><span class="p">({</span> <span class="nx">room</span><span class="o">:</span> <span class="s1">'signaller-getting-started'</span> <span class="p">});</span>
</pre></div>
<h2 id="signaller-events">Signaller Events</h2>
<p>There are a number of events that are generating throughout the lifecycle of a signaller.</p>
<h3 id="events-regarding-local-state">Events regarding local state</h3>
<p>The following events are generated by the signaller in response to updates n it's own state:</p>
<ul>
<li><p><code>connected</code></p>
<p>A connection has been established via the underlying messenger to a signalling server (or equivalent).</p>
</li>
<li><p><code>disconnected</code></p>
<p>The connection has been lost (possibly temporarily) with the signalling server (or transport). It is possible that the connection will be re-established so this does not necessarily mean the end.</p>
</li>
<li><p><code>local:announce</code></p>
<p>This event is trigged when an <code>/announce</code> message is sent via the messenging channel. The event includes a single <code>data</code> argument which contains the object data that has been sent.</p>
</li>
</ul>
<h3 id="events-regarding-peer-state">Events regarding peer state</h3>
<p>The following events relate to information that has been relayed to this signaller about other peers:</p>
<ul>
<li><p><code>peer:filter</code></p>
<p>The <code>peer:filter</code> event is triggered prior to the <code>peer:announce</code> or <code>peer:update</code> events being fired and provides an application the opportunity to reject a peer. The handler for this event is passed the id of the peer that has connected to the room and a JS <code>data</code> object for the announce data. This data only differs from the <code>peer:announce</code> (or <code>peer:update</code>) data in that an <code>allow</code> attribute is included and controls whether we will acknowledge the presence of this new peer.</p>
<p>Due to the way event emitters behave in node, the last handler invoked is the authority on whether the peer is accepted or not (so make sure to check the previous state of the allow flag):</p>
<div class="highlight"><pre><span class="c1">// only accept connections from Bob</span>
<span class="nx">signaller</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'peer:filter'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">data</span><span class="p">.</span><span class="nx">allow</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">allow</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="s1">'Bob'</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
</li>
<li><p><code>peer:connected</code></p>
<p>If a peer has passed the <code>peer:filter</code> test (either no filtering has been applied, or the allow flag is set to true in the filter events) then a <code>peer:connected</code> event will be emitted:</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'peer:connected'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'peer '</span> <span class="o">+</span> <span class="nx">id</span> <span class="o">+</span> <span class="s1">' has connected'</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
<p>This event can be useful if you wish to know when a peer has connected to the signalling server, and don't care whether it is a new peer (generating a <code>peer:announce</code> event) or known peer (generating a <code>peer:update</code> event).</p>
</li>
<li><p><code>peer:announce</code></p>
<p>While the <code>peer:connected</code> event is triggered each time a peer reconnects and announces to the signalling server, a <code>peer:announce</code> event is only emitted by your local signaller if this is considered a new connection from a peer.</p>
<p>If you are writing a WebRTC application, then this event is the best place to start creating <code>RTCPeerConnection</code> objects between the local machine and your remote, announced counterpart. You will then be able to <a href="https://github.com/rtc-io/rtc#rtccouple">couple</a> those connections together using the signaller.</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'peer:announce'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'discovered new peer: '</span> <span class="o">+</span> <span class="nx">data</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="c1">// TODO: create a peer connection with our new friend :)</span>
<span class="p">});</span>
</pre></div>
</li>
<li><p><code>peer:update</code></p>
<p>An existing peer in the system has been "re-announced" possibly with some data changes:</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'peer:update'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'data update from peer: '</span> <span class="o">+</span> <span class="nx">data</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
</li>
</ul>
<h2 id="signal-flow-diagrams">Signal Flow Diagrams</h2>
<p>Displayed below are some diagrams how the signalling flow between peers behaves. In each of the diagrams we illustrate three peers (A, B and C) participating discovery and coordinating RTCPeerConnection handshakes.</p>
<p>In each case, only the interaction between the clients is represented not how a signalling server (such as <a href="https://github.com/rtc-io/rtc-switchboard">rtc-switchboard</a>) would pass on broadcast messages, etc. This is done for two reasons:</p>
<ol>
<li>It is out of scope of this documentation.</li>
<li>The <code>rtc-signaller</code> has been designed to work without having to rely on any intelligence in the server side signalling component. In the instance that a signaller broadcasts all messages to all connected peers then <code>rtc-signaller</code> should be smart enough to make sure everything works as expected.</li>
</ol>
<h3 id="peer-discovery-announcement">Peer Discovery / Announcement</h3>
<p>This diagram illustrates the process of how peer <code>A</code> announces itself to peers <code>B</code> and <code>C</code>, and in turn they announce themselves.</p>
<p><img src="https://raw.github.com/rtc-io/rtc-signaller/master/docs/announce.png" alt=""></p>
<h3 id="editing-updating-the-diagrams">Editing / Updating the Diagrams</h3>
<p>Each of the diagrams has been generated using <a href="http://www.mcternan.me.uk/mscgen/index.html">mscgen</a> and the source for these documents can be found in the <code>docs/</code> folder of this repository.</p>
<h2 id="reference">Reference</h2>
<p>The <code>rtc-signaller</code> module is designed to be used primarily in a functional
way and when called it creates a new signaller that will enable
you to communicate with other peers via your messaging network.</p>
<div class="highlight"><pre><span class="c1">// create a signaller from something that knows how to send messages</span>
<span class="kd">var</span> <span class="nx">signaller</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'rtc-signaller'</span><span class="p">)(</span><span class="nx">messenger</span><span class="p">);</span>
</pre></div>
<p>As demonstrated in the getting started guide, you can also pass through
a string value instead of a messenger instance if you simply want to
connect to an existing <code>rtc-switchboard</code> instance.</p>
<h3 id="-signaller-connect-"><code>signaller.connect()</code></h3>
<p>Manually connect the signaller using the supplied messenger.</p>
<p><strong>NOTE:</strong> This should never have to be called if the default setting
for <code>autoconnect</code> is used.</p>
<h3 id="announce-data-">announce(data?)</h3>
<p>The <code>announce</code> function of the signaller will pass an <code>/announce</code> message
through the messenger network. When no additional data is supplied to
this function then only the id of the signaller is sent to all active
members of the messenging network.</p>
<h4 id="joining-rooms">Joining Rooms</h4>
<p>To join a room using an announce call you simply provide the name of the
room you wish to join as part of the data block that you annouce, for
example:</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">announce</span><span class="p">({</span> <span class="nx">room</span><span class="o">:</span> <span class="s1">'testroom'</span> <span class="p">});</span>
</pre></div>
<p>Signalling servers (such as
<a href="https://github.com/rtc-io/rtc-switchboard">rtc-switchboard</a>) will then
place your peer connection into a room with other peers that have also
announced in this room.</p>
<p>Once you have joined a room, the server will only deliver messages that
you <code>send</code> to other peers within that room.</p>
<h4 id="providing-additional-announce-data">Providing Additional Announce Data</h4>
<p>There may be instances where you wish to send additional data as part of
your announce message in your application. For instance, maybe you want
to send an alias or nick as part of your announce message rather than just
use the signaller's generated id.</p>
<p>If for instance you were writing a simple chat application you could join
the <code>webrtc</code> room and tell everyone your name with the following announce
call:</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">announce</span><span class="p">({</span>
<span class="nx">room</span><span class="o">:</span> <span class="s1">'webrtc'</span><span class="p">,</span>
<span class="nx">nick</span><span class="o">:</span> <span class="s1">'Damon'</span>
<span class="p">});</span>
</pre></div>
<h4 id="announcing-updates">Announcing Updates</h4>
<p>The signaller is written to distinguish between initial peer announcements
and peer data updates (see the docs on the announce handler below). As
such it is ok to provide any data updates using the announce method also.</p>
<p>For instance, I could send a status update as an announce message to flag
that I am going offline:</p>
<div class="highlight"><pre><span class="nx">signaller</span><span class="p">.</span><span class="nx">announce</span><span class="p">({</span> <span class="nx">status</span><span class="o">:</span> <span class="s1">'offline'</span> <span class="p">});</span>
</pre></div>
<h3 id="leave-">leave()</h3>
<p>Tell the signalling server we are leaving. Calling this function is
usually not required though as the signalling server should issue correct
<code>/leave</code> messages when it detects a disconnect event.</p>
<h2 id="license-s-">License(s)</h2>
<h3 id="apache-2-0">Apache 2.0</h3>
<p>Copyright 2013 - 2014 National ICT Australia Limited (NICTA)</p>
<p> Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at</p>
<pre><code> http://www.apache.org/licenses/LICENSE-2.0</code></pre>
<p> Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</p>
</div>
<footer>
<p>
<a href="http://nicta.com.au">
<img src="images/nicta-logo.gif" alt="NICTA logo">
</a>© NICTA 2013 - 2014
</p>
<p class="license">Project source code is licensed under the <a href="https://github.com/rtc-io/rtc/blob/master/LICENSE">Apache 2.0</a>.</p>
<a class="closing" href="#top"></a>
</footer>
</body>
<script src="js/app.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-26567546-2', 'rtc.io');
ga('send', 'pageview');
</script>
</html>