WebRTC - Draft

WebRTC #

Web Real-Time Communication

Overview #

  • A protocol that connects peer to peer
  • Find a peer to peer path to exchange video and audio in an efficient and low latency manner
  • Standardized API
  • Enables rich communications browsers, mobile, IOT devices

Demo #

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebRTC Manual SDP Exchange</title>
</head>
<body>
  <h1>WebRTC Manual SDP Exchange</h1>

  <div>
    <h3>Client 1 (Create Offer)</h3>
    <button id="startChannel">Start Channel</button>
    <textarea id="offerSDP" readonly placeholder="SDP Offer" style="width: 100%; height: 100px;"></textarea>
  </div>
  
  <div>
    <h3>Client 2 (Enter Offer and Respond)</h3>
    <textarea id="offerInput" placeholder="Paste SDP Offer Here" style="width: 100%; height: 100px;"></textarea>
    <button id="respondOffer">Respond to Offer</button>
    <textarea id="answerSDP" readonly placeholder="SDP Answer" style="width: 100%; height: 100px;"></textarea>
  </div>

  <div>
    <h3>Client 1 (Set SDP Answer)</h3>
    <textarea id="answerInput" placeholder="Paste SDP Answer Here" style="width: 100%; height: 100px;"></textarea>
    <button id="setAnswer">Set Answer</button>
  </div>

  <div>
    <h3>Communication</h3>
    <textarea id="chatArea" readonly style="width: 100%; height: 150px;"></textarea>
    <br />
    <input type="text" id="messageInput" placeholder="Type a message..." style="width: 80%;" />
    <button id="sendMessage" disabled>Send</button>
  </div>

  <script src="webrtc-demo.js"></script>
</body>
</html>
const startChannelButton = document.getElementById('startChannel');
const offerSDPTextarea = document.getElementById('offerSDP');
const offerInputTextarea = document.getElementById('offerInput');
const respondOfferButton = document.getElementById('respondOffer');
const answerSDPTextarea = document.getElementById('answerSDP');
const answerInputTextarea = document.getElementById('answerInput');
const setAnswerButton = document.getElementById('setAnswer');
const sendButton = document.getElementById('sendMessage');
const chatArea = document.getElementById('chatArea');
const messageInput = document.getElementById('messageInput');

let localConnection, remoteConnection, sendChannel, receiveChannel;

// Start channel and create SDP offer (Client 1)
startChannelButton.onclick = async () => {
  localConnection = new RTCPeerConnection();

  // Create data channel
  sendChannel = localConnection.createDataChannel('chat');
  sendChannel.onopen = handleChannelStatusChange;
  sendChannel.onclose = handleChannelStatusChange;

  // Handle ICE candidates
  localConnection.onicecandidate = e => {
    if (!e.candidate) {
      offerSDPTextarea.value = JSON.stringify(localConnection.localDescription);
    }
  };

  // Create an SDP offer
  const offer = await localConnection.createOffer();
  await localConnection.setLocalDescription(offer);
};

// Respond to offer and create SDP answer (Client 2)
respondOfferButton.onclick = async () => {
  const offer = JSON.parse(offerInputTextarea.value);

  remoteConnection = new RTCPeerConnection();
  remoteConnection.onicecandidate = e => {
    if (!e.candidate) {
      answerSDPTextarea.value = JSON.stringify(remoteConnection.localDescription);
    }
  };

  // Handle incoming data channel
  remoteConnection.ondatachannel = e => {
    receiveChannel = e.channel;
    receiveChannel.onmessage = handleReceiveMessage;
    receiveChannel.onopen = handleChannelStatusChange;
    receiveChannel.onclose = handleChannelStatusChange;
  };

  // Set remote description from offer
  await remoteConnection.setRemoteDescription(offer);

  // Create an SDP answer
  const answer = await remoteConnection.createAnswer();
  await remoteConnection.setLocalDescription(answer);
};

// Set SDP answer on Client 1
setAnswerButton.onclick = async () => {
  const answer = JSON.parse(answerInputTextarea.value);
  if (localConnection) {
    await localConnection.setRemoteDescription(answer);
  }
};

// Send messages
sendButton.onclick = () => {
  const message = messageInput.value.trim();
  if (message && sendChannel.readyState === 'open') {
    sendChannel.send(message);
    appendMessage(`You: ${message}`);
    messageInput.value = '';
  }
};

// Append messages to chat area
function appendMessage(message) {
  chatArea.value += `${message}\n`;
}

// Handle received messages
function handleReceiveMessage(event) {
  appendMessage(`Peer: ${event.data}`);
}

// Handle channel status changes
function handleChannelStatusChange() {
  if (sendChannel && sendChannel.readyState === 'open') {
    messageInput.disabled = false;
    sendButton.disabled = false;
  } else {
    messageInput.disabled = true;
    sendButton.disabled = true;
  }
}