Skip to content

Commit 326c898

Browse files
committed
intial
1 parent 922f4f3 commit 326c898

File tree

12 files changed

+1159
-8959
lines changed

12 files changed

+1159
-8959
lines changed

README.md

Lines changed: 331 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,350 @@
11
# react-native-simple-peer
22

3-
To building an exciting peer-to-peer WebRTC-based mobile Application
3+
To building Simple WebRTC video, voice, and data channels through peer-to-peer WebRTC-based mobile Application
4+
5+
6+
## features
7+
8+
- concise, **node.js style** API for [WebRTC](https://en.wikipedia.org/wiki/WebRTC)
9+
- **works in node and the browser!**
10+
- supports **video/voice streams**
11+
- supports **data channel**
12+
- text and binary data
13+
- node.js [duplex stream](http://nodejs.org/api/stream.html) interface
14+
- supports advanced options like:
15+
- enable/disable [trickle ICE candidates](http://webrtchacks.com/trickle-ice/)
16+
- manually set config options
17+
- transceivers and renegotiation
18+
19+
## Example Source Codes
20+
- [React Native](example)
21+
- [Node Js Server](example/server)
22+
- [React Js](example/reactjs)
23+
- [Live Server](https://meet-app-video.herokuapp.com)
424

525
## Installation
626

27+
### NPM
28+
729
```sh
830
npm install react-native-simple-peer
931
```
1032

33+
### Yarn
34+
35+
```sh
36+
yarn add react-native-simple-peer
37+
```
38+
1139
## Usage
1240

41+
42+
### A simpler example
43+
44+
This example create two peers **in the same page**.
45+
46+
### data channels
47+
1348
```js
14-
import { multiply } from "react-native-simple-peer";
49+
var Peer = require('simple-peer')
50+
51+
import RNSimplePeer from "react-native-simple-peer";
52+
53+
const peer1 = new RNSimplePeer({ initiator: true })
54+
const peer2 = new RNSimplePeer()
1555

16-
// ...
56+
peer1.on('signal', data => {
57+
// when peer1 has signaling data, give it to peer2 somehow
58+
peer2.signal(data)
59+
})
1760

18-
const result = await multiply(3, 7);
61+
peer2.on('signal', data => {
62+
// when peer2 has signaling data, give it to peer1 somehow
63+
peer1.signal(data)
64+
})
65+
66+
peer1.on('connect', () => {
67+
// wait for 'connect' event before using the data channel
68+
peer1.send('hey peer2, how is it going?')
69+
})
70+
71+
peer2.on('data', data => {
72+
// got a data channel message
73+
console.log('got a message from peer1: ' + data)
74+
})
1975
```
2076

77+
### video/voice
78+
79+
Video/voice is also super simple! In this example, peer1 sends video to peer2.
80+
81+
```js
82+
import RNSimplePeer from "react-native-simple-peer";
83+
import { mediaDevices } from "react-native-webrtc"
84+
85+
// get video/voice stream
86+
mediaDevices.getUserMedia({
87+
audio: true,
88+
video: {
89+
width: 640,
90+
height: 480,
91+
frameRate: 30,
92+
facingMode: "user",
93+
deviceId: videoSourceId
94+
}
95+
}).then(gotMedia).catch(() => {})
96+
97+
function gotMedia (stream) {
98+
var peer1 = new RNSimplePeer({ initiator: true, stream: stream })
99+
var peer2 = new RNSimplePeer()
100+
101+
peer1.on('signal', data => {
102+
peer2.signal(data)
103+
})
104+
105+
peer2.on('signal', data => {
106+
peer1.signal(data)
107+
})
108+
109+
peer2.on('stream', stream => {
110+
// got remote video stream, now let's show it in a video tag
111+
var video = document.querySelector('video')
112+
113+
if ('srcObject' in video) {
114+
video.srcObject = stream
115+
} else {
116+
video.src = window.URL.createObjectURL(stream) // for older browsers
117+
}
118+
119+
video.play()
120+
})
121+
}
122+
```
123+
124+
For two-way video, simply pass a `stream` option into both `Peer` constructors. Simple!
125+
126+
127+
## RNSimplePeer Configs
128+
129+
key props | type | defualts | descriptions
130+
--- | --- | --- | ---
131+
initiator | boolean | false | set to `true` if this is the initiating peer
132+
channelConfig | RTCDataChannelInit/undefined | {} | custom webrtc data channel configuration
133+
channelName | string/undefined | Random String | custom webrtc data channel name
134+
config | RTCConfiguration/undefined | { } | custom webrtc configuration
135+
offerOptions | RTCOfferOptions/undefined | {} | custom offer options
136+
answerOptions | RTCAnswerOptions/undefined | {} | custom answer options
137+
sdpTransform | Function | (instance, sdp) => {} | function to transform the generated SDP signaling data
138+
streams | Array<MediaStream>/undefined | undefined | video/voice streams
139+
stream | MediaStream/undefined | undefined | video/voice stream
140+
trickle | boolean | false | set to `false` to disable trickle ICE and get a single 'signal' event
141+
allowHalfTrickle | boolean | false | determines how long to wait before providing an offer or answer
142+
iceCompleteTimeout | number | 5000 | how long to wait before providing an offer or answer
143+
debugConsole | boolean | true | to show debug console
144+
webRTC | Object | {RTCIceCandidate, RTCPeerConnection, RTCSessionDescription} | Set Webrtc classess
145+
146+
147+
## RNSimplePeer Methods
148+
Method | descriptions
149+
--- | ---
150+
peer.signal(data) | Call this method whenever the remote peer emits a peer.on('signal') event. The data will encapsulate a webrtc offer, answer, or ice candidate.
151+
peer.send(data) | Send text/binary data to the remote peer.
152+
peer.addStream(stream) | Add a MediaStream to the connection.
153+
peer.removeStream(stream) | Remove a MediaStream from the connection.
154+
peer.addTrack(track, stream) | Add a MediaStreamTrack to the connection. Must also pass the MediaStream you want to attach it to.
155+
peer.removeTrack(track, stream) | Remove a MediaStreamTrack from the connection. Must also pass the MediaStream that it was attached to.
156+
peer.replaceTrack(oldTrack, newTrack, stream) | Replace a MediaStreamTrack with another track. Must also pass the MediaStream that the old track was attached to.
157+
peer.addTransceiver(kind, init) | Add a RTCRtpTransceiver to the connection. Can be used to add transceivers before adding tracks. Automatically called addTrack.
158+
peer.destroy([err]) | Destroy and cleanup If the optional err parameter is passed, then it will be emitted as an 'error' event on the stream.
159+
160+
161+
## RNSimplePeer Events
162+
163+
Event | descriptions
164+
--- | ---
165+
peer.removeAllListeners('close') | removing all registered close-event listeners
166+
peer.on('signal', data => {}) | Fired when the peer wants to send signaling data to the remote peer.
167+
peer.on('connect', () => {}) | Fired when the peer connection and data channel are ready to use.
168+
peer.on('data', data => {}) | Received a message from the remote peer (via the data channel).
169+
peer.on('stream', stream => {}) | Received a remote video stream
170+
peer.on('track', (track, stream) => {}) | Received a remote audio/video track. Streams may contain multiple tracks.
171+
peer.on('close', () => {}) | Called when the peer connection has closed.
172+
peer.on('error', (err) => {}) | Fired when a fatal error occurs. Usually, this means bad signaling data was received from the remote peer.
173+
174+
175+
### duplex stream
176+
177+
`Peer` objects are instances of `stream.Duplex`. They behave very similarly to a
178+
`net.Socket` from the node core `net` module. The duplex stream reads/writes to the data
179+
channel.
180+
181+
```js
182+
var peer = new RNSimplePeer(props)
183+
// ... signaling ...
184+
peer.write(new Buffer('hey'))
185+
peer.on('data', function (chunk) {
186+
console.log('got a chunk', chunk)
187+
})
188+
```
189+
190+
## error codes
191+
192+
Errors returned by the `error` event have an `err.code` property that will indicate the origin of the failure.
193+
194+
Possible error codes:
195+
- `ERR_WEBRTC_SUPPORT`
196+
- `ERR_CREATE_OFFER`
197+
- `ERR_CREATE_ANSWER`
198+
- `ERR_SET_LOCAL_DESCRIPTION`
199+
- `ERR_SET_REMOTE_DESCRIPTION`
200+
- `ERR_ADD_ICE_CANDIDATE`
201+
- `ERR_ICE_CONNECTION_FAILURE`
202+
- `ERR_SIGNALING`
203+
- `ERR_DATA_CHANNEL`
204+
- `ERR_CONNECTION_FAILURE`
205+
206+
## connecting more than 2 peers?
207+
208+
The simplest way to do that is to create a full-mesh topology. That means that every peer
209+
opens a connection to every other peer. To illustrate:
210+
211+
![full mesh topology](docs/images/full-mesh.png)
212+
213+
To broadcast a message, just iterate over all the peers and call `peer.send`.
214+
215+
So, say you have 3 peers. Then, when a peer wants to send some data it must send it 2
216+
times, once to each of the other peers. So you're going to want to be a bit careful about
217+
the size of the data you send.
218+
219+
Full mesh topologies don't scale well when the number of peers is very large. The total
220+
number of edges in the network will be ![full mesh formula](docs/images/full-mesh-formula.png)
221+
where `n` is the number of peers.
222+
223+
For clarity, here is the code to connect 3 peers together:
224+
225+
#### Peer 1
226+
227+
```js
228+
// These are peer1's connections to peer2 and peer3
229+
var peer2 = new RNSimplePeer({ initiator: true })
230+
var peer3 = new RNSimplePeer({ initiator: true })
231+
232+
peer2.on('signal', data => {
233+
// send this signaling data to peer2 somehow
234+
})
235+
236+
peer2.on('connect', () => {
237+
peer2.send('hi peer2, this is peer1')
238+
})
239+
240+
peer2.on('data', data => {
241+
console.log('got a message from peer2: ' + data)
242+
})
243+
244+
peer3.on('signal', data => {
245+
// send this signaling data to peer3 somehow
246+
})
247+
248+
peer3.on('connect', () => {
249+
peer3.send('hi peer3, this is peer1')
250+
})
251+
252+
peer3.on('data', data => {
253+
console.log('got a message from peer3: ' + data)
254+
})
255+
```
256+
257+
#### Peer 2
258+
259+
```js
260+
// These are peer2's connections to peer1 and peer3
261+
var peer1 = new RNSimplePeer()
262+
var peer3 = new RNSimplePeer({ initiator: true })
263+
264+
peer1.on('signal', data => {
265+
// send this signaling data to peer1 somehow
266+
})
267+
268+
peer1.on('connect', () => {
269+
peer1.send('hi peer1, this is peer2')
270+
})
271+
272+
peer1.on('data', data => {
273+
console.log('got a message from peer1: ' + data)
274+
})
275+
276+
peer3.on('signal', data => {
277+
// send this signaling data to peer3 somehow
278+
})
279+
280+
peer3.on('connect', () => {
281+
peer3.send('hi peer3, this is peer2')
282+
})
283+
284+
peer3.on('data', data => {
285+
console.log('got a message from peer3: ' + data)
286+
})
287+
```
288+
289+
#### Peer 3
290+
291+
```js
292+
// These are peer3's connections to peer1 and peer2
293+
var peer1 = new RNSimplePeer()
294+
var peer2 = new RNSimplePeer()
295+
296+
peer1.on('signal', data => {
297+
// send this signaling data to peer1 somehow
298+
})
299+
300+
peer1.on('connect', () => {
301+
peer1.send('hi peer1, this is peer3')
302+
})
303+
304+
peer1.on('data', data => {
305+
console.log('got a message from peer1: ' + data)
306+
})
307+
308+
peer2.on('signal', data => {
309+
// send this signaling data to peer2 somehow
310+
})
311+
312+
peer2.on('connect', () => {
313+
peer2.send('hi peer2, this is peer3')
314+
})
315+
316+
peer2.on('data', data => {
317+
console.log('got a message from peer2: ' + data)
318+
})
319+
```
320+
321+
## memory usage
322+
323+
If you call `peer.send(buf)`, `simple-peer` is not keeping a reference to `buf`
324+
and sending the buffer at some later point in time. We immediately call
325+
`channel.send()` on the data channel. So it should be fine to mutate the buffer
326+
right afterward.
327+
328+
However, beware that `peer.write(buf)` (a writable stream method) does not have
329+
the same contract. It will potentially buffer the data and call
330+
`channel.send()` at a future point in time, so definitely don't assume it's
331+
safe to mutate the buffer.
332+
333+
334+
## connection does not work on some networks?
335+
336+
If a direct connection fails, in particular, because of NAT traversal and/or firewalls,
337+
WebRTC ICE uses an intermediary (relay) TURN server. In other words, ICE will first use
338+
STUN with UDP to directly connect peers and, if that fails, will fall back to a TURN relay
339+
server.
340+
341+
In order to use a TURN server, you must specify the `config` option to the `Peer`
342+
constructor. See the API docs above.
343+
344+
### Donate
345+
346+
<p><a href="https://www.paypal.me/ajithab" rel="nofollow"><img height="75" src="https://raw.githubusercontent.com/stefan-niedermann/paypal-donate-button/master/paypal-donate-button.png" style="max-width:100%;"></a></p>
347+
21348
## Contributing
22349

23350
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

example/app.json

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,4 @@
11
{
2-
"name": "react-native-simple-peer-example",
3-
"displayName": "SimplePeer Example",
4-
"expo": {
5-
"name": "react-native-simple-peer-example",
6-
"slug": "react-native-simple-peer-example",
7-
"description": "Example app for react-native-simple-peer",
8-
"privacy": "public",
9-
"version": "1.0.0",
10-
"platforms": [
11-
"ios",
12-
"android",
13-
"web"
14-
],
15-
"ios": {
16-
"supportsTablet": true
17-
},
18-
"assetBundlePatterns": [
19-
"**/*"
20-
]
21-
}
2+
"name": "SimplePeerExample",
3+
"displayName": "SimplePeer Example"
224
}

0 commit comments

Comments
 (0)