text: /*
   *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
  
  'use strict';
  
  let localConnection;
  let remoteConnection;
  let sendChannel;
  let receiveChannel;
  const dataChannelSend = document.querySelector('textarea#dataChannelSend');
  const dataChannelReceive = document.querySelector('textarea#dataChannelReceive');
  const startButton = document.querySelector('button#startButton');
  const sendButton = document.querySelector('button#sendButton');
  const closeButton = document.querySelector('button#closeButton');
  
  startButton.onclick = createConnection;
  sendButton.onclick = sendData;
  closeButton.onclick = closeDataChannels;
  
  function enableStartButton() {
    startButton.disabled = false;
  }
  
  function disableSendButton() {
    sendButton.disabled = true;
  }
  
  function createConnection() {
    dataChannelSend.placeholder = '';
    const servers = null;
    window.localConnection = localConnection = new RTCPeerConnection(servers);
    console.log('Created local peer connection object localConnection');
  
    sendChannel = localConnection.createDataChannel('sendDataChannel');
    console.log('Created send data channel');
  
    localConnection.onicecandidate = e => {
      onIceCandidate(localConnection, e);
    };
    sendChannel.onopen = onSendChannelStateChange;
    sendChannel.onclose = onSendChannelStateChange;
  
    window.remoteConnection = remoteConnection = new RTCPeerConnection(servers);
    console.log('Created remote peer connection object remoteConnection');
  
    remoteConnection.onicecandidate = e => {
      onIceCandidate(remoteConnection, e);
    };
    remoteConnection.ondatachannel = receiveChannelCallback;
  
    localConnection.createOffer().then(
        gotDescription1,
        onCreateSessionDescriptionError
    );
    startButton.disabled = true;
    closeButton.disabled = false;
  }
  
  function onCreateSessionDescriptionError(error) {
    console.log('Failed to create session description: ' + error.toString());
  }
  
  function sendData() {
    const data = dataChannelSend.value;
    sendChannel.send(data);
    console.log('Sent Data: ' + data);
  }
  
  function closeDataChannels() {
    console.log('Closing data channels');
    sendChannel.close();
    console.log('Closed data channel with label: ' + sendChannel.label);
    receiveChannel.close();
    console.log('Closed data channel with label: ' + receiveChannel.label);
    localConnection.close();
    remoteConnection.close();
    localConnection = null;
    remoteConnection = null;
    console.log('Closed peer connections');
    startButton.disabled = false;
    sendButton.disabled = true;
    closeButton.disabled = true;
    dataChannelSend.value = '';
    dataChannelReceive.value = '';
    dataChannelSend.disabled = true;
    disableSendButton();
    enableStartButton();
  }
  
  function gotDescription1(desc) {
    localConnection.setLocalDescription(desc);
    console.log(`Offer from localConnection\n${desc.sdp}`);
    remoteConnection.setRemoteDescription(desc);
    remoteConnection.createAnswer().then(
        gotDescription2,
        onCreateSessionDescriptionError
    );
  }
  
  function gotDescription2(desc) {
    remoteConnection.setLocalDescription(desc);
    console.log(`Answer from remoteConnection\n${desc.sdp}`);
    localConnection.setRemoteDescription(desc);
  }
  
  function getOtherPc(pc) {
    return (pc === localConnection) ? remoteConnection : localConnection;
  }
  
  function getName(pc) {
    return (pc === localConnection) ? 'localPeerConnection' : 'remotePeerConnection';
  }
  
  function onIceCandidate(pc, event) {
    getOtherPc(pc)
        .addIceCandidate(event.candidate)
        .then(
            () => onAddIceCandidateSuccess(pc),
            err => onAddIceCandidateError(pc, err)
        );
    console.log(`${getName(pc)} ICE candidate: ${event.candidate ? event.candidate.candidate : '(null)'}`);
  }
  
  function onAddIceCandidateSuccess() {
    console.log('AddIceCandidate success.');
  }
  
  function onAddIceCandidateError(error) {
    console.log(`Failed to add Ice Candidate: ${error.toString()}`);
  }
  
  function receiveChannelCallback(event) {
    console.log('Receive Channel Callback');
    receiveChannel = event.channel;
    receiveChannel.onmessage = onReceiveMessageCallback;
    receiveChannel.onopen = onReceiveChannelStateChange;
    receiveChannel.onclose = onReceiveChannelStateChange;
  }
  
  function onReceiveMessageCallback(event) {
    console.log('Received Message');
    dataChannelReceive.value = event.data;
  }
  
  function onSendChannelStateChange() {
    const readyState = sendChannel.readyState;
    console.log('Send channel state is: ' + readyState);
    if (readyState === 'open') {
      dataChannelSend.disabled = false;
      dataChannelSend.focus();
      sendButton.disabled = false;
      closeButton.disabled = false;
    } else {
      dataChannelSend.disabled = true;
      sendButton.disabled = true;
      closeButton.disabled = true;
    }
  }
  
  function onReceiveChannelStateChange() {
    const readyState = receiveChannel.readyState;
    console.log(`Receive channel state is: ${readyState}`);
  }
  