WebRTC - RTCPeerConnection APIs


Advertisements

The RTCPeerConnection API is the core of the peer-to-peer connection between each of the browsers. To create the RTCPeerConnection objects simply write

var pc = RTCPeerConnection(config);

where the config argument contains at least on key, iceServers. It is an array of URL objects containing information about STUN and TURN servers, used during the finding of the ICE candidates. You can find a list of available public STUN servers at code.google.com

Depending upon whether you are the caller or the callee the RTCPeerConnection object is used in a slightly different way on each side of the connection.

Here is an example of the user's flow −

  • Register the onicecandidate handler. It sends any ICE candidates to the other peer, as they are received.

  • Register the onaddstream handler. It handles the displaying of the video stream once it is received from the remote peer.

  • Register the message handler. Your signaling server should also have a handler for messages received from the other peer. If the message contains the RTCSessionDescription object, it should be added to the RTCPeerConnection object using the setRemoteDescription() method. If the message contains the RTCIceCandidate object, it should be added to the RTCPeerConnection object using the addIceCandidate() method.

  • Utilize getUserMedia() to set up your local media stream and add it to the RTCPeerConnection object using the addStream() method.

  • Start offer/answer negotiation process. This is the only step where the caller's flow is different from the callee's one. The caller starts negotiation using the createOffer() method and registers a callback that receives the RTCSessionDescription object. Then this callback should add this RTCSessionDescription object to your RTCPeerConnection object using setLocalDescription(). And finally, the caller should send this RTCSessionDescription to the remote peer using the signaling server. The callee, on the other, registers the same callback, but in the createAnswer() method. Notice that the callee flow is initiated only after the offer is received from the caller.

RTCPeerConnection API

Properties

  • RTCPeerConnection.iceConnectionState (read only) − Returns an RTCIceConnectionState enum that describes the state of the connection. An iceconnectionstatechange event is fired when this value changes. The possible values −

    • new − the ICE agent is waiting for remote candidates or gathering addresses

    • checking − the ICE agent has remote candidates, but it has not found a connection yet

    • connected − the ICE agent has found a usable connection, but is still checking more remote candidate for better connection.

    • completed − the ICE agent has found a usable connection and stopped testing remote candidates.

    • failed − the ICE agent has checked all the remote candidates but didn't find a match for at least one component.

    • disconnected − at least one component is no longer alive.

    • closed − the ICE agent is closed.

  • RTCPeerConnection.iceGatheringState (read only) − Returns a RTCIceGatheringState enum that describes the ICE gathering state for the connection −

    • new − the object was just created.

    • gathering − the ICE agent is in the process of gathering candidates

    • complete the ICE agent has completed gathering.

  • RTCPeerConnection.localDescription (read only) − Returns an RTCSessionDescription describing the local session. It can be null if it has not yet been set.

  • RTCPeerConnection.peerIdentity (read only) − Returns an RTCIdentityAssertion. It consists of an idp(domain name) and a name representing the identity of the remote peer.

  • RTCPeerConnection.remoteDescription (read only) − Return an RTCSessionDescription describing the remote session. It can be null if it has not yet been set.

  • RTCPeerConnection.signalingState (read only) − Returns an RTCSignalingState enum that describes the signaling state of the local connection. This state describes the SDP offer. A signalingstatechange event is fired when this value changes. The possible values −

    • stable − The initial state. There is no SDP offer/answer exchange in progress.

    • have-local-offer − the local side of the connection has locally applied a SDP offer.

    • have-remote-offer − the remote side of the connection has locally applied a SDP offer.

    • have-local-pranswer − a remote SDP offer has been applied, and a SDP pranswer applied locally.

    • have-remote-pranswer − a local SDP has been applied, and a SDP pranswer applied remotely.

    • closed − the connection is closed.

Event Handlers

S.No. Event Handlers & Description
1

RTCPeerConnection.onaddstream

This handler is called when the addstream event is fired. This event is sent when a MediaStream is added to this connection by the remote peer.

2

RTCPeerConnection.ondatachannel

This handler is called when the datachannel event is fired. This event is sent when a RTCDataChannel is added to this connection.

3

RTCPeerConnection.onicecandidate

This handler is called when the icecandidate event is fired. This event is sent when a RTCIceCandidate object is added to the script.

4

RTCPeerConnection.oniceconnectionstatechange

This handler is called when the iceconnectionstatechange event is fired. This event is sent when the value of iceConnectionState changes.

5

RTCPeerConnection.onidentityresult

This handler is called when the identityresult event is fired. This event is sent when an identity assertion is generated during the creating of an offer or an answer of via getIdentityAssertion().

6

RTCPeerConnection.onidpassertionerror

This handler is called when the idpassertionerror event is fired. This event is sent when the IdP (Identitry Provider) finds an error while generating an identity assertion.

7

RTCPeerConnection.onidpvalidation

This handler is called when the idpvalidationerror event is fired. This event is sent when the IdP (Identitry Provider) finds an error while validating an identity assertion.

8

RTCPeerConnection.onnegotiationneeded

This handler is called when the negotiationneeded event is fired. This event is sent by the browser to inform the negotiation will be required at some point in the future.

9

RTCPeerConnection.onpeeridentity

This handler is called when the peeridentity event is fired. This event is sent when a peer identity has been set and verified on this connection.

10

RTCPeerConnection.onremovestream

This handler is called when the signalingstatechange event is fired. This event is sent when the value of signalingState changes.

11

RTCPeerConnection.onsignalingstatechange

This handler is called when the removestream event is fired. This event is sent when a MediaStream is removed from this connection.

Methods

S.No. Methods & Description
1

RTCPeerConnection()

Returns a new RTCPeerConnection object.

2

RTCPeerConnection.createOffer()

Creates an offer(request) to find a remote peer. The two first parameters of this method are success and error callbacks. The optional third parameter are options, like enabling audio or video streams.

3

RTCPeerConnection.createAnswer()

Creates an answer to the offer received by the remote peer during the offer/answer negotiation process. The two first parameters of this method are success and error callbacks. The optional third parameter are options for the answer to be created.

4

RTCPeerConnection.setLocalDescription()

Changes the local connection description. The description defines the properties of the connection. The connection must be able to support both old and new descriptions. The method takes three parameters, RTCSessionDescription object, callback if the change of description succeeds, callback if the change of description fails.

5

RTCPeerConnection.setRemoteDescription()

Changes the remote connection description. The description defines the properties of the connection. The connection must be able to support both old and new descriptions. The method takes three parameters, RTCSessionDescription object, callback if the change of description succeeds, callback if the change of description fails.

6

RTCPeerConnection.updateIce()

Updates the ICE agent process of pinging remote candidates and gathering local candidates.

7

RTCPeerConnection.addIceCandidate()

Provides a remote candidate to the ICE agent.

8

RTCPeerConnection.getConfiguration()

Returns a RTCConfiguration object. It represents the configuration of the RTCPeerConnection object.

9

RTCPeerConnection.getLocalStreams()

Returns an array of local MediaStream connection.

10

RTCPeerConnection.getRemoteStreams()

Returns an array of remote MediaStream connection.

11

RTCPeerConnection.getStreamById()

Returns local or remote MediaStream by the given ID.

12

RTCPeerConnection.addStream()

Adds a MediaStream as a local source of video or audio.

13

RTCPeerConnection.removeStream()

Removes a MediaStream as a local source of video or audio.

14

RTCPeerConnection.close()

Closes a connection.

15

RTCPeerConnection.createDataChannel()

Creates a new RTCDataChannel.

16

RTCPeerConnection.createDTMFSender()

Creates a new RTCDTMFSender, associated to a specific MediaStreamTrack. Allows to send DTMF (Dual-tone multifrequency) phone signaling over the connection.

17

RTCPeerConnection.getStats()

Creates a new RTCStatsReport that contains statistics concerning the connection.

18

RTCPeerConnection.setIdentityProvider()

Sets the IdP. Takes three parameters − the name, the protocol used to communicate and an optional username.

19

RTCPeerConnection.getIdentityAssertion()

Gathers an identity assertion. It is not expected to deal with this method in the application. So you may call it explicitly only to anticipate the need.

Establishing a Connection

Now let's create an example application. Firstly, run the signaling server we created in the “signaling server” tutorial via “node server”.

There will be two text inputs on the page, one for a login and one for a username we want to connect to. Create an index.html file and add the following code −

<html lang = "en"> 
   <head> 
      <meta charset = "utf-8" /> 
   </head>
	
   <body> 
	
      <div> 
         <input type = "text" id = "loginInput" /> 
         <button id = "loginBtn">Login</button> 
      </div> 
	
      <div> 
         <input type = "text" id = "otherUsernameInput" />
         <button id = "connectToOtherUsernameBtn">Establish connection</button> 
      </div> 
		
      <script src = "client2.js"></script>
		
   </body>
	
</html>

You can see that we've added the text input for a login, the login button, the text input for the other peer username, and the connect-to-him button. Now create a client.js file and add the following code −

var connection = new WebSocket('ws://localhost:9090'); 
var name = ""; 
 
var loginInput = document.querySelector('#loginInput'); 
var loginBtn = document.querySelector('#loginBtn'); 
var otherUsernameInput = document.querySelector('#otherUsernameInput'); 
var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn'); 
var connectedUser, myConnection;
  
//when a user clicks the login button 
loginBtn.addEventListener("click", function(event){ 
   name = loginInput.value; 
	
   if(name.length > 0){ 
      send({ 
         type: "login", 
         name: name 
      }); 
   } 
	
});
  
//handle messages from the server 
connection.onmessage = function (message) { 
   console.log("Got message", message.data);
   var data = JSON.parse(message.data); 
	
   switch(data.type) { 
      case "login": 
         onLogin(data.success); 
         break; 
      case "offer": 
         onOffer(data.offer, data.name); 
         break; 
      case "answer": 
         onAnswer(data.answer); 
         break; 
      case "candidate": 
         onCandidate(data.candidate); 
         break; 
      default: 
         break; 
   } 
};
  
//when a user logs in 
function onLogin(success) { 

   if (success === false) { 
      alert("oops...try a different username"); 
   } else { 
      //creating our RTCPeerConnection object 
		
      var configuration = { 
         "iceServers": [{ "url": "stun:stun.1.google.com:19302" }] 
      }; 
		
      myConnection = new webkitRTCPeerConnection(configuration); 
      console.log("RTCPeerConnection object was created"); 
      console.log(myConnection); 
  
      //setup ice handling
      //when the browser finds an ice candidate we send it to another peer 
      myConnection.onicecandidate = function (event) { 
		
         if (event.candidate) { 
            send({ 
               type: "candidate", 
               candidate: event.candidate 
            }); 
         } 
      }; 
   } 
};
  
connection.onopen = function () { 
   console.log("Connected"); 
};
  
connection.onerror = function (err) { 
   console.log("Got error", err); 
};
  
// Alias for sending messages in JSON format 
function send(message) { 

   if (connectedUser) { 
      message.name = connectedUser; 
   } 
	
   connection.send(JSON.stringify(message)); 
};

You can see that we establish a socket connection to our signaling server. When a user clicks on the login button the application sends his username to the server. If login is successful the application creates the RTCPeerConnection object and setup onicecandidate handler which sends all found icecandidates to the other peer. Now open the page and try to login. You should see the following console output −

Establishing a Connection

The next step is to create an offer to the other peer. Add the following code to your client.js file −

//setup a peer connection with another user 
connectToOtherUsernameBtn.addEventListener("click", function () { 
 
   var otherUsername = otherUsernameInput.value; 
   connectedUser = otherUsername;
	
   if (otherUsername.length > 0) { 
      //make an offer 
      myConnection.createOffer(function (offer) { 
         console.log(); 
         send({ 
            type: "offer", 
            offer: offer 
         });
			
         myConnection.setLocalDescription(offer); 
      }, function (error) { 
         alert("An error has occurred."); 
      }); 
   } 
}); 
 
//when somebody wants to call us 
function onOffer(offer, name) { 
   connectedUser = name; 
   myConnection.setRemoteDescription(new RTCSessionDescription(offer)); 
	
   myConnection.createAnswer(function (answer) { 
      myConnection.setLocalDescription(answer); 
		
      send({ 
         type: "answer", 
         answer: answer 
      }); 
		
   }, function (error) { 
      alert("oops...error"); 
   }); 
}
  
//when another user answers to our offer 
function onAnswer(answer) { 
   myConnection.setRemoteDescription(new RTCSessionDescription(answer)); 
} 
 
//when we got ice candidate from another user 
function onCandidate(candidate) { 
   myConnection.addIceCandidate(new RTCIceCandidate(candidate)); 
}	

You can see that when a user clicks the “Establish connection” button the application makes an SDP offer to the other peer. We also set onAnswer and onCandidate handlers. Reload your page, open it in two tabs, login with two users and try to establish a connection between them. You should see the following console output −

Console Output

Now the peer-to-peer connection is established. In the next tutorials, we will add video and audio streams as well as text chat support.

Advertisements