blob: 9161966a78ae2be0b4345472066d24d48c662872 [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001'use strict';
2
3/**
4 * A WebRTC peer connection helper. Tightly coupled with the signaling
5 * class.
6 */
7class WebRTCPeerConnection {
8 constructor(signaling, offering, configuration = null) {
9 // Set default configuration (if none provided)
10 if (configuration === null) {
11 configuration = {
12 iceServers: [{
13 urls: 'stun:stun.services.mozilla.com',
14 }],
15 };
16 }
17
18 // Create peer connection and bind events
19 const pc = new RTCPeerConnection(configuration);
20 pc._offering = offering; // Meh!
21 signaling.pc = pc;
22 pc.onnegotiationneeded = async () => {
23 console.log('Negotiation needed');
24
25 // Create offer (if required)
26 if (offering) {
27 console.log('Creating offer');
28 const description = await pc.createOffer();
29 await pc.setLocalDescription(description);
30 signaling.handleLocalDescription(description);
31 }
32 };
33 pc.signalingstatechange = () => {
34 console.log('Signaling state:', pc.signalingState);
35 };
36 pc.oniceconnectionstatechange = () => {
37 console.log('ICE connection state:', pc.iceConnectionState);
38 };
39 pc.onicegatheringstatechange = () => {
40 console.log('ICE gathering state:', pc.iceGatheringState);
41 };
42 pc.onconnectionstatechange = () => {
43 console.log('Connection state:', pc.connectionState);
44 };
45 pc.onicecandidate = (event) => {
46 signaling.handleLocalCandidate(event.candidate);
47 };
48 pc.onicecandidateerror = (event) => {
49 console.error('ICE candidate error:', event);
50 };
51 pc.ondatachannel = (event) => {
52 const dc = event.channel;
53 console.log('Incoming data channel:', dc.label);
54
55 // Bind events
56 this.bindDataChannelEvents(dc);
57 };
58
59 // Store configuration & signalling instance
60 this.pc = pc;
61 this.dcs = {};
62 }
63
64 createDataChannel(name, options = null) {
65 const pc = this.pc;
66
67 // Create data channel and bind events
68 const dc = pc.createDataChannel(name, options);
69 this.bindDataChannelEvents(dc);
70
71 // Store data channel and return
72 this.dcs[name] = dc;
73 return dc;
74 }
75
76 bindDataChannelEvents(dc) {
77 dc._name = dc.label; // Meh!
78 dc.onopen = () => {
79 console.log(dc._name, 'open');
80 };
81 dc.onclose = () => {
82 console.log(dc._name, 'closed');
83 };
84 dc.onerror = (event) => {
85 console.log(dc._name, 'error:', event);
86 };
87 dc.onbufferedamountlow = () => {
88 console.log(dc._name, 'buffered amount low:', dc.bufferedAmount);
89 };
90 dc.onmessage = (event) => {
91 const size = event.data.byteLength || event.data.size;
92 console.log(dc._name, 'incoming message (' + size + ' bytes)');
93 };
94 }
95}