Squashed 'third_party/rawrtc/rawrtc/' content from commit aa3ae4b24
Change-Id: I38a655a4259b62f591334e90a1315bd4e7e4d8ec
git-subtree-dir: third_party/rawrtc/rawrtc
git-subtree-split: aa3ae4b247275cc6e69c30613b3a4ba7fdc82d1b
diff --git a/htdocs/webrtc/peerconnection.js b/htdocs/webrtc/peerconnection.js
new file mode 100644
index 0000000..9161966
--- /dev/null
+++ b/htdocs/webrtc/peerconnection.js
@@ -0,0 +1,95 @@
+'use strict';
+
+/**
+ * A WebRTC peer connection helper. Tightly coupled with the signaling
+ * class.
+ */
+class WebRTCPeerConnection {
+ constructor(signaling, offering, configuration = null) {
+ // Set default configuration (if none provided)
+ if (configuration === null) {
+ configuration = {
+ iceServers: [{
+ urls: 'stun:stun.services.mozilla.com',
+ }],
+ };
+ }
+
+ // Create peer connection and bind events
+ const pc = new RTCPeerConnection(configuration);
+ pc._offering = offering; // Meh!
+ signaling.pc = pc;
+ pc.onnegotiationneeded = async () => {
+ console.log('Negotiation needed');
+
+ // Create offer (if required)
+ if (offering) {
+ console.log('Creating offer');
+ const description = await pc.createOffer();
+ await pc.setLocalDescription(description);
+ signaling.handleLocalDescription(description);
+ }
+ };
+ pc.signalingstatechange = () => {
+ console.log('Signaling state:', pc.signalingState);
+ };
+ pc.oniceconnectionstatechange = () => {
+ console.log('ICE connection state:', pc.iceConnectionState);
+ };
+ pc.onicegatheringstatechange = () => {
+ console.log('ICE gathering state:', pc.iceGatheringState);
+ };
+ pc.onconnectionstatechange = () => {
+ console.log('Connection state:', pc.connectionState);
+ };
+ pc.onicecandidate = (event) => {
+ signaling.handleLocalCandidate(event.candidate);
+ };
+ pc.onicecandidateerror = (event) => {
+ console.error('ICE candidate error:', event);
+ };
+ pc.ondatachannel = (event) => {
+ const dc = event.channel;
+ console.log('Incoming data channel:', dc.label);
+
+ // Bind events
+ this.bindDataChannelEvents(dc);
+ };
+
+ // Store configuration & signalling instance
+ this.pc = pc;
+ this.dcs = {};
+ }
+
+ createDataChannel(name, options = null) {
+ const pc = this.pc;
+
+ // Create data channel and bind events
+ const dc = pc.createDataChannel(name, options);
+ this.bindDataChannelEvents(dc);
+
+ // Store data channel and return
+ this.dcs[name] = dc;
+ return dc;
+ }
+
+ bindDataChannelEvents(dc) {
+ dc._name = dc.label; // Meh!
+ dc.onopen = () => {
+ console.log(dc._name, 'open');
+ };
+ dc.onclose = () => {
+ console.log(dc._name, 'closed');
+ };
+ dc.onerror = (event) => {
+ console.log(dc._name, 'error:', event);
+ };
+ dc.onbufferedamountlow = () => {
+ console.log(dc._name, 'buffered amount low:', dc.bufferedAmount);
+ };
+ dc.onmessage = (event) => {
+ const size = event.data.byteLength || event.data.size;
+ console.log(dc._name, 'incoming message (' + size + ' bytes)');
+ };
+ }
+}