10.4 Peer-to-peer Data Example

This example shows how to create an RTCDataChannel object and perform the offer/answer exchange required to connect the channel to the other peer. The RTCDataChannel is used in the context of a simple chat application using an input field for user input.

Example 12

  1. const signaling = new SignalingChannel(); // handles JSON.stringify/parse
  2. const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
  3. let pc, channel;
  4. // call start() to initiate
  5. function start() {
  6. pc = new RTCPeerConnection(configuration);
  7. // send any ice candidates to the other peer
  8. pc.onicecandidate = ({candidate}) => signaling.send({candidate});
  9. // let the "negotiationneeded" event trigger offer generation
  10. pc.onnegotiationneeded = async () => {
  11. try {
  12. await pc.setLocalDescription();
  13. // send the offer to the other peer
  14. signaling.send({description: pc.localDescription});
  15. } catch (err) {
  16. console.error(err);
  17. }
  18. };
  19. // create data channel and setup chat using "negotiated" pattern
  20. channel = pc.createDataChannel('chat', {negotiated: true, id: 0});
  21. channel.onopen = () => input.disabled = false;
  22. channel.onmessage = ({data}) => showChatMessage(data);
  23. input.onkeypress = ({keyCode}) => {
  24. // only send when user presses enter
  25. if (keyCode != 13) return;
  26. channel.send(input.value);
  27. }
  28. }
  29. signaling.onmessage = async ({data: {description, candidate}}) => {
  30. if (!pc) start(false);
  31. try {
  32. if (description) {
  33. await pc.setRemoteDescription(description);
  34. // if we got an offer, we need to reply with an answer
  35. if (description.type == 'offer') {
  36. await pc.setLocalDescription();
  37. signaling.send({description: pc.localDescription});
  38. }
  39. } else if (candidate) {
  40. await pc.addIceCandidate(candidate);
  41. }
  42. } catch (err) {
  43. console.error(err);
  44. }
  45. };