WebRTC - Sesli Demo

Bu bölümde, iki kullanıcının ayrı cihazlarda WebRTC ses akışlarını kullanarak iletişim kurmasına olanak tanıyan bir istemci uygulaması oluşturacağız. Uygulamamız iki sayfadan oluşacaktır. Biri oturum açmak için, diğeri başka bir kullanıcıya sesli arama yapmak için.

İki sayfa div etiketleri olacaktır. Girişlerin çoğu basit olay işleyicileri aracılığıyla yapılır.

Sinyal Sunucusu

Bir WebRTC bağlantısı oluşturmak için istemcilerin bir WebRTC eş bağlantısı kullanmadan mesajları aktarabilmesi gerekir. Burada iki uç nokta arasında çift yönlü bir soket bağlantısı olan HTML5 WebSockets'i kullanacağız - bir web sunucusu ve bir web tarayıcısı. Şimdi WebSocket kitaplığını kullanmaya başlayalım. Server.js dosyasını oluşturun ve aşağıdaki kodu ekleyin -

//require our websocket library 
var WebSocketServer = require('ws').Server; 

//creating a websocket server at port 9090 
var wss = new WebSocketServer({port: 9090});
  
//when a user connects to our sever 
wss.on('connection', function(connection) { 
   console.log("user connected"); 
	
   //when server gets a message from a connected user 
   connection.on('message', function(message) { 
      console.log("Got message from a user:", message); 
   }); 
	
   connection.send("Hello from server"); 
});

İlk satır, önceden kurmuş olduğumuz WebSocket kitaplığını gerektirir. Ardından 9090 portunda bir soket sunucusu oluşturuyoruz. Ardından bağlantı olayını dinliyoruz . Bu kod, bir kullanıcı sunucuya bir WebSocket bağlantısı yaptığında çalıştırılacaktır. Daha sonra kullanıcı tarafından gönderilen mesajları dinliyoruz. Son olarak bağlanan kullanıcıya "Sunucudan merhaba" diyen bir yanıt gönderiyoruz.

Sinyal verme sunucumuzda, her bağlantı için dizeye dayalı bir kullanıcı adı kullanacağız, böylece mesajları nereye göndereceğimizi bileceğiz. En bizim değiştirelim bağlantı işleyicisi biraz -

connection.on('message', function(message) { 
   var data; 
	
   //accepting only JSON messages 
   try { 
      data = JSON.parse(message); 
   } catch (e) { 
      console.log("Invalid JSON");
      data = {}; 
   } 
});

Bu şekilde sadece JSON mesajlarını kabul ediyoruz. Sonra, tüm bağlı kullanıcıları bir yerde saklamamız gerekiyor. Bunun için basit bir Javascript nesnesi kullanacağız. Dosyamızın üstünü değiştirin -

//require our websocket library 
var WebSocketServer = require('ws').Server; 

//creating a websocket server at port 9090 
var wss = new WebSocketServer({port: 9090}); 

//all connected to the server users 
var users = {};

Müşteriden gelen her mesaj için bir tip alanı ekleyeceğiz . Örneğin, bir kullanıcı giriş yapmak isterse, giriş türü mesajını gönderir . Tanımlayalım -

connection.on('message', function(message) {
  
   var data; 
   //accepting only JSON messages 
   try { 
      data = JSON.parse(message); 
   } catch (e) { 
      console.log("Invalid JSON"); 
      data = {}; 
   } 
	
   //switching type of the user message 
   switch (data.type) { 
      //when a user tries to login 
      case "login": 
         console.log("User logged:", data.name); 
			
         //if anyone is logged in with this username then refuse 
         if(users[data.name]) { 
            sendTo(connection, { 
               type: "login",
               success: false 
            }); 
         } else { 
            //save user connection on the server 
            users[data.name] = connection; 
            connection.name = data.name; 
				
            sendTo(connection, { 
               type: "login", 
               success: true 
            }); 
         } 
			
         break;
			
      default: 
         sendTo(connection, { 
            type: "error", 
            message: "Command no found: " + data.type 
         }); 
			
         break; 
   }  
});

Kullanıcı, giriş türü ile bir mesaj gönderirse , biz -

  • Bu kullanıcı adıyla zaten giriş yapan biri olup olmadığını kontrol edin.
  • Öyleyse, kullanıcıya başarıyla oturum açmadığını söyleyin.
  • Bu kullanıcı adını kimse kullanmıyorsa, kullanıcı adını bağlantı nesnesine anahtar olarak ekleriz.
  • Bir komut tanınmazsa, bir hata göndeririz.

Aşağıdaki kod, bir bağlantıya mesaj göndermek için yardımcı bir işlevdir. Bunu server.js dosyasına ekleyin -

function sendTo(connection, message) { 
   connection.send(JSON.stringify(message)); 
}

Kullanıcı bağlantısı kesildiğinde bağlantısını temizlemeliyiz. Kapanış olayı tetiklendiğinde kullanıcıyı silebiliriz . Bağlantı işleyicisine aşağıdaki kodu ekleyin−

connection.on("close", function() { 
   if(connection.name) { 
      delete users[connection.name]; 
   } 
});

Başarılı bir şekilde oturum açtıktan sonra, kullanıcı başka birini aramak ister. Bunu başarmak için başka bir kullanıcıya teklif vermelidir . Teklif işleyiciyi ekleyin -

case "offer": 
   //for ex. UserA wants to call UserB 
   console.log("Sending offer to: ", data.name); 
	
   //if UserB exists then send him offer details 
   var conn = users[data.name]; 
	
   if(conn != null) { 
      //setting that UserA connected with UserB 
      connection.otherName = data.name; 
      sendTo(conn, { 
         type: "offer", 
         offer: data.offer, 
         name: connection.name 
      });
   }		
	
   break;

Öncelikle aramaya çalıştığımız kullanıcının bağlantısını alıyoruz. Varsa, ona teklif ayrıntılarını göndeririz . Biz de eklemek otherName için bağlantı nesnesi. Bu, daha sonra bulmanın basitliği için yapılmıştır.

Yanıtı yanıtlamak, teklif işleyicide kullandığımız benzer bir modele sahiptir . Sunucumuz tüm mesajları başka bir kullanıcıya cevap olarak geçirir . Teklif işleyiciden sonra aşağıdaki kodu ekleyin -

case "answer": 
   console.log("Sending answer to: ", data.name); 
   //for ex. UserB answers UserA
   var conn = users[data.name]; 
	
   if(conn != null) { 
      connection.otherName = data.name;
		
      sendTo(conn, { 
         type: "answer", 
         answer: data.answer 
      }); 
   } 
	
   break;

Son kısım, kullanıcılar arasında ICE adayını ele almaktır. Mesajları kullanıcılar arasında iletmekle aynı tekniği kullanıyoruz. Temel fark, aday mesajlarının herhangi bir sırada kullanıcı başına birden çok kez olabilmesidir. Aday işleyiciyi ekleyin -

case "candidate": 
   console.log("Sending candidate to:",data.name); 
   var conn = users[data.name];
	
   if(conn != null) { 
      sendTo(conn, { 
         type: "candidate", 
         candidate: data.candidate 
      }); 
   } 
	
   break;

Kullanıcılarımızın başka bir kullanıcıyla bağlantısını kesmelerine izin vermek için, kapatma işlevini uygulamalıyız. Ayrıca sunucuya tüm kullanıcı referanslarını silmesini söyleyecektir. İzin işleyicisini ekleyin -

case "leave": 
   console.log("Disconnecting from", data.name); 
   var conn = users[data.name]; 
   conn.otherName = null; 
	
   //notify the other user so he can disconnect his peer connection 
   if(conn != null) { 
      sendTo(conn, {
         type: "leave" 
      }); 
   }  
	
   break;

Bu aynı zamanda diğer kullanıcıya ayrılma olayını da gönderecek, böylece eş bağlantısını uygun şekilde kesebilecektir. Bir kullanıcı sinyal sunucusundan bağlantısını kestiğinde de durumu ele almalıyız. Yakın işleyicimizi değiştirelim -

connection.on("close", function() { 

   if(connection.name) { 
      delete users[connection.name]; 
		
      if(connection.otherName) { 
         console.log("Disconnecting from ", connection.otherName); 
         var conn = users[connection.otherName]; 
         conn.otherName = null;
			
         if(conn != null) { 
            sendTo(conn, { 
               type: "leave" 
            }); 
         }
			
      } 
   } 
});

Aşağıdaki, sinyal sunucumuzun kodunun tamamıdır -

//require our websocket library 
var WebSocketServer = require('ws').Server; 

//creating a websocket server at port 9090 
var wss = new WebSocketServer({port: 9090}); 

//all connected to the server users 
var users = {};

//when a user connects to our sever 
wss.on('connection', function(connection) {
  
   console.log("User connected");
	
   //when server gets a message from a connected user 
   connection.on('message', function(message) { 
	
      var data;
		
      //accepting only JSON messages 
      try { 
         data = JSON.parse(message); 
      } catch (e) { 
         console.log("Invalid JSON"); 
         data = {}; 
      }
		
      //switching type of the user message 
      switch (data.type) { 
         //when a user tries to login 
         case "login": 
            console.log("User logged", data.name); 
				
            //if anyone is logged in with this username then refuse 
            if(users[data.name]) { 
               sendTo(connection, { 
                  type: "login", 
                  success: false 
               }); 
            } else { 
               //save user connection on the server 
               users[data.name] = connection; 
               connection.name = data.name;
					
               sendTo(connection, { 
                  type: "login", 
                  success: true 
               }); 
            } 
				
            break;
				
         case "offer": 
            //for ex. UserA wants to call UserB 
            console.log("Sending offer to: ", data.name); 
				
            //if UserB exists then send him offer details 
            var conn = users[data.name]; 
				
            if(conn != null) { 
               //setting that UserA connected with UserB 
               connection.otherName = data.name; 
					
               sendTo(conn, { 
                  type: "offer", 
                  offer: data.offer, 
                  name: connection.name 
               }); 
            } 
				
            break;
				
         case "answer": 
            console.log("Sending answer to: ", data.name); 
            //for ex. UserB answers UserA 
            var conn = users[data.name]; 
				
            if(conn != null) { 
               connection.otherName = data.name; 
               sendTo(conn, { 
                  type: "answer", 
                  answer: data.answer 
               });
            } 
				
            break;
				
         case "candidate": 
            console.log("Sending candidate to:",data.name); 
            var conn = users[data.name];  
				
            if(conn != null) { 
               sendTo(conn, { 
                  type: "candidate", 
                  candidate: data.candidate 
               }); 
            } 
				
            break;
				
         case "leave": 
            console.log("Disconnecting from", data.name); 
            var conn = users[data.name]; 
            conn.otherName = null; 
				
            //notify the other user so he can disconnect his peer connection 
            if(conn != null) { 
               sendTo(conn, { 
                  type: "leave" 
               }); 
            }  
				
            break;
				
         default: 
            sendTo(connection, { 
               type: "error", 
               message: "Command not found: " + data.type 
            });
				
            break; 
      }  
   });
	
   //when user exits, for example closes a browser window 
   //this may help if we are still in "offer","answer" or "candidate" state 
   connection.on("close", function() { 
	
      if(connection.name) { 
         delete users[connection.name]; 
			
         if(connection.otherName) { 
            console.log("Disconnecting from ", connection.otherName); 
            var conn = users[connection.otherName]; 
            conn.otherName = null;  
				
            if(conn != null) { 
               sendTo(conn, { 
                  type: "leave" 
              }); 
            }  
         } 
      } 
   });  
	
   connection.send("Hello world"); 
}); 
 
function sendTo(connection, message) { 
   connection.send(JSON.stringify(message)); 
}

İstemci Uygulaması

Bu uygulamayı test etmenin bir yolu, iki tarayıcı sekmesi açmak ve birbirlerine sesli arama yapmaya çalışmaktır.

Öncelikle bootstrap kütüphanesini kurmamız gerekiyor . Bootstrap, web uygulamaları geliştirmek için bir ön uç çerçevesidir. Daha fazla bilgi edinebilirsinizhttp://getbootstrap.com/.Örneğin, "sesli sohbet" adlı bir klasör oluşturun. Bu bizim kök uygulama klasörümüz olacak. Bu klasörün içinde bir package.json dosyası oluşturun (npm bağımlılıklarını yönetmek için gereklidir) ve aşağıdakileri ekleyin -

{ 
   "name": "webrtc-audiochat", 
   "version": "0.1.0", 
   "description": "webrtc-audiochat", 
   "author": "Author", 
   "license": "BSD-2-Clause" 
}

Ardından npm install bootstrap komutunu çalıştırın . Bu, bootstrap kitaplığını audiochat / node_modules klasörüne kuracaktır .

Şimdi temel bir HTML sayfası oluşturmamız gerekiyor. Aşağıdaki kodla kök klasörde bir index.html dosyası oluşturun -

<html>
 
   <head> 
      <title>WebRTC Voice Demo</title> 
      <link rel = "stylesheet" href = "node_modules/bootstrap/dist/css/bootstrap.min.css"/> 
   </head>
 
   <style> 
      body { 
         background: #eee; 
         padding: 5% 0; 
      } 
   </style>
	
   <body> 
      <div id = "loginPage" class = "container text-center"> 
		
         <div class = "row"> 
            <div class = "col-md-4 col-md-offset-4">
				
               <h2>WebRTC Voice Demo. Please sign in</h2>
				
               <label for = "usernameInput" class = "sr-only">Login</label> 
               <input type = "email" id = "usernameInput" 
                  class = "form-control formgroup"
                  placeholder = "Login" required = "" autofocus = ""> 
               <button id = "loginBtn" class = "btn btn-lg btn-primary btnblock">
                  Sign in</button> 
            </div> 
         </div> 
			
      </div>
		
      <div id = "callPage" class = "call-page">
		
         <div class = "row"> 
			
            <div class = "col-md-6 text-right"> 
               Local audio: <audio id = "localAudio" 
               controls autoplay></audio> 
            </div>
				
            <div class = "col-md-6 text-left"> 
               Remote audio: <audio id = "remoteAudio" 
                  controls autoplay></audio> 
            </div> 
				
         </div> 
			
         <div class = "row text-center"> 
            <div class = "col-md-12"> 
               <input id = "callToUsernameInput" 
                  type = "text" placeholder = "username to call" /> 
               <button id = "callBtn" class = "btn-success btn">Call</button> 
               <button id = "hangUpBtn" class = "btn-danger btn">Hang Up</button> 
            </div> 
         </div>
			
      </div> 
		
      <script src = "client.js"></script> 
		
   </body>
	
</html>

Bu sayfa size tanıdık gelmelidir. Bootstrap css dosyasını ekledik . Ayrıca iki sayfa tanımladık. Son olarak, kullanıcıdan bilgi almak için birkaç metin alanı ve düğme oluşturduk. Yerel ve uzak ses akışları için iki ses öğesini görmelisiniz. Client.js dosyasına bir bağlantı eklediğimize dikkat edin .

Şimdi sinyal sunucumuzla bir bağlantı kurmamız gerekiyor. Oluştur client.js aşağıdaki kodla kök klasöre -

//our username 
var name; 
var connectedUser;
  
//connecting to our signaling server 
var conn = new WebSocket('ws://localhost:9090');
  
conn.onopen = function () { 
   console.log("Connected to the signaling server"); 
}; 
 
//when we got a message from a signaling server 
conn.onmessage = function (msg) { 
   console.log("Got message", msg.data);  
   var data = JSON.parse(msg.data);  
	
   switch(data.type) { 
      case "login": 
         handleLogin(data.success); 
         break; 
      //when somebody wants to call us 
      case "offer": 
         handleOffer(data.offer, data.name); 
         break; 
      case "answer": 
         handleAnswer(data.answer); 
         break; 
      //when a remote peer sends an ice candidate to us 
      case "candidate": 
         handleCandidate(data.candidate); 
         break;
      case "leave": 
         handleLeave(); 
         break; 
      default: 
         break; 
   } 
};
  
conn.onerror = function (err) { 
   console.log("Got error", err); 
};
  
//alias for sending JSON encoded messages 
function send(message) { 
   //attach the other peer username to our messages
   if (connectedUser) { 
      message.name = connectedUser; 
   } 
	
   conn.send(JSON.stringify(message)); 
};

Şimdi sinyal sunucumuzu düğüm sunucusu aracılığıyla çalıştırın . Ardından, kök klasörün içinde statik komutu çalıştırın ve tarayıcı içindeki sayfayı açın. Aşağıdaki konsol çıktısını görmelisiniz -

Bir sonraki adım, benzersiz bir kullanıcı adıyla bir kullanıcı girişi uygulamaktır. Sunucuya sadece bir kullanıcı adı göndeririz, bu da bize bunun alınıp alınmadığını söyler. Aşağıdaki kodu client.js dosyanıza ekleyin -

//****** 
//UI selectors block 
//******

var loginPage = document.querySelector('#loginPage'); 
var usernameInput = document.querySelector('#usernameInput'); 
var loginBtn = document.querySelector('#loginBtn');
 
var callPage = document.querySelector('#callPage'); 
var callToUsernameInput = document.querySelector('#callToUsernameInput');
var callBtn = document.querySelector('#callBtn');
 
var hangUpBtn = document.querySelector('#hangUpBtn');
  
callPage.style.display = "none";
  
// Login when the user clicks the button 
loginBtn.addEventListener("click", function (event) { 
   name = usernameInput.value;
	
   if (name.length > 0) { 
      send({
         type: "login", 
         name: name 
      }); 
   } 
	
}); 
 
function handleLogin(success) { 
   if (success === false) { 
      alert("Ooops...try a different username"); 
   } else { 
      loginPage.style.display = "none"; 
      callPage.style.display = "block"; 
		
      //********************** 
      //Starting a peer connection 
      //**********************
		         
   } 
	
};

İlk olarak, sayfadaki elemanlara bazı referanslar seçiyoruz. Çağrı sayfasını gizleriz. Ardından, giriş butonuna bir olay dinleyicisi ekliyoruz. Kullanıcı tıkladığında, kullanıcı adını sunucuya göndeririz. Son olarak, handleLogin geri aramasını gerçekleştiriyoruz. Giriş başarılı olduysa, arama sayfasını gösteririz ve bir eş bağlantı kurmaya başlarız.

Akran bağlantısı başlatmak için ihtiyacımız olan -

  • Bir mikrofondan ses akışı elde edin
  • RTCPeerConnection nesnesini oluşturun

Aşağıdaki kodu "UI seçici bloğuna" ekleyin -

var localAudio = document.querySelector('#localAudio'); 
var remoteAudio = document.querySelector('#remoteAudio'); 

var yourConn; 
var stream;

HandleLogin işlevini değiştirin -

function handleLogin(success) { 
   if (success === false) { 
      alert("Ooops...try a different username"); 
   } else { 
      loginPage.style.display = "none"; 
      callPage.style.display = "block";
		
      //********************** 
      //Starting a peer connection 
      //********************** 
		
      //getting local audio stream 
      navigator.webkitGetUserMedia({ video: false, audio: true }, function (myStream) { 
         stream = myStream; 
			
         //displaying local audio stream on the page
         localAudio.src = window.URL.createObjectURL(stream);
			
         //using Google public stun server 
         var configuration = { 
            "iceServers": [{ "url": "stun:stun2.1.google.com:19302" }] 
         }; 
			
         yourConn = new webkitRTCPeerConnection(configuration); 
			
         // setup stream listening 
         yourConn.addStream(stream); 
			
         //when a remote user adds stream to the peer connection, we display it 
         yourConn.onaddstream = function (e) { 
            remoteAudio.src = window.URL.createObjectURL(e.stream); 
         }; 
			
         // Setup ice handling 
         yourConn.onicecandidate = function (event) { 
            if (event.candidate) { 
               send({ 
                  type: "candidate", 
               }); 
            } 
         };  
			
      }, function (error) { 
         console.log(error); 
      }); 
		
   } 
};

Şimdi kodu çalıştırırsanız, sayfa oturum açmanıza ve sayfada yerel ses akışınızı görüntülemenize izin vermelidir.

Şimdi bir çağrı başlatmaya hazırız. Öncelikle başka bir kullanıcıya teklif gönderiyoruz . Bir kullanıcı teklifi aldıktan sonra bir cevap oluşturur ve ICE adaylarının ticaretine başlar. Aşağıdaki kodu client.js dosyasına ekleyin -

//initiating a call 
callBtn.addEventListener("click", function () { 
   var callToUsername = callToUsernameInput.value; 
	
   if (callToUsername.length > 0) { 
      connectedUser = callToUsername; 
		
      // create an offer 
      yourConn.createOffer(function (offer) { 
         send({ 
            type: "offer", 
            offer: offer 
         }); 
			
         yourConn.setLocalDescription(offer); 
			
      }, function (error) { 
         alert("Error when creating an offer"); 
      }); 
   } 
	
});
 
//when somebody sends us an offer 
function handleOffer(offer, name) { 
   connectedUser = name; 
   yourConn.setRemoteDescription(new RTCSessionDescription(offer)); 
	
   //create an answer to an offer 
   yourConn.createAnswer(function (answer) { 
      yourConn.setLocalDescription(answer); 
		
      send({ 
         type: "answer",
         answer: answer 
      }); 
		
   }, function (error) { 
      alert("Error when creating an answer"); 
   }); 
	
};
 
//when we got an answer from a remote user 
function handleAnswer(answer) { 
   yourConn.setRemoteDescription(new RTCSessionDescription(answer)); 
};
 
//when we got an ice candidate from a remote user 
function handleCandidate(candidate) { 
   yourConn.addIceCandidate(new RTCIceCandidate(candidate)); 
};

Çağrı düğmesine bir teklif başlatan bir tıklama işleyici ekliyoruz . Ardından onmessage işleyicisinin beklediği birkaç işleyiciyi uygularız . Her iki kullanıcı da bir bağlantı kurana kadar eşzamansız olarak işleneceklerdir.

Son adım, kapatma özelliğini uygulamaktır. Bu, veri aktarımını durduracak ve diğer kullanıcıya aramayı kapatmasını söyleyecektir. Aşağıdaki kodu ekleyin -

//hang up 
hangUpBtn.addEventListener("click", function () { 
   send({ 
      type: "leave" 
   });  
	
   handleLeave(); 
});
  
function handleLeave() { 
   connectedUser = null; 
   remoteAudio.src = null;
	
   yourConn.close(); 
   yourConn.onicecandidate = null; 
   yourConn.onaddstream = null;
};

Kullanıcı Kapat düğmesini tıkladığında -

  • Diğer kullanıcıya bir "ayrılma" mesajı gönderecek
  • RTCPeerConnection'ı kapatacak ve bağlantıyı yerel olarak yok edecek

Şimdi kodu çalıştırın. İki tarayıcı sekmesi kullanarak sunucuda oturum açabilmelisiniz. Daha sonra sekmeye sesli arama yapabilir ve aramayı kapatabilirsiniz.

Aşağıdaki tüm client.js dosyasıdır -

//our username 
var name; 
var connectedUser;
 
//connecting to our signaling server 
var conn = new WebSocket('ws://localhost:9090');
 
conn.onopen = function () { 
   console.log("Connected to the signaling server"); 
};
 
//when we got a message from a signaling server 
conn.onmessage = function (msg) { 
   console.log("Got message", msg.data); 
   var data = JSON.parse(msg.data); 
	
   switch(data.type) { 
      case "login": 
         handleLogin(data.success); 
         break; 
      //when somebody wants to call us 
      case "offer": 
         handleOffer(data.offer, data.name); 
         break; 
      case "answer": 
         handleAnswer(data.answer); 
         break; 
      //when a remote peer sends an ice candidate to us 
      case "candidate": 
         handleCandidate(data.candidate); 
         break; 
      case "leave": 
         handleLeave(); 
         break; 
      default: 
         break; 
   } 
}; 

conn.onerror = function (err) { 
   console.log("Got error", err); 
};
 
//alias for sending JSON encoded messages 
function send(message) { 
   //attach the other peer username to our messages 
   if (connectedUser) { 
      message.name = connectedUser; 
   } 
	
   conn.send(JSON.stringify(message)); 
};
 
//****** 
//UI selectors block 
//****** 

var loginPage = document.querySelector('#loginPage'); 
var usernameInput = document.querySelector('#usernameInput'); 
var loginBtn = document.querySelector('#loginBtn');

var callPage = document.querySelector('#callPage'); 
var callToUsernameInput = document.querySelector('#callToUsernameInput');
var callBtn = document.querySelector('#callBtn'); 

var hangUpBtn = document.querySelector('#hangUpBtn'); 
var localAudio = document.querySelector('#localAudio'); 
var remoteAudio = document.querySelector('#remoteAudio'); 

var yourConn; 
var stream; 

callPage.style.display = "none";
 
// Login when the user clicks the button 
loginBtn.addEventListener("click", function (event) { 
   name = usernameInput.value; 
	
   if (name.length > 0) { 
      send({ 
         type: "login", 
         name: name 
      }); 
   } 
	
});
 
function handleLogin(success) { 
   if (success === false) { 
      alert("Ooops...try a different username"); 
   } else { 
      loginPage.style.display = "none"; 
      callPage.style.display = "block"; 
		
      //********************** 
      //Starting a peer connection 
      //********************** 
		
      //getting local audio stream 
      navigator.webkitGetUserMedia({ video: false, audio: true }, function (myStream) { 
         stream = myStream; 
			
         //displaying local audio stream on the page 
         localAudio.src = window.URL.createObjectURL(stream);
			
         //using Google public stun server 
         var configuration = { 
            "iceServers": [{ "url": "stun:stun2.1.google.com:19302" }] 
         }; 
			
         yourConn = new webkitRTCPeerConnection(configuration); 
			
         // setup stream listening 
         yourConn.addStream(stream); 
			
         //when a remote user adds stream to the peer connection, we display it 
         yourConn.onaddstream = function (e) { 
            remoteAudio.src = window.URL.createObjectURL(e.stream); 
         }; 
			
         // Setup ice handling 
         yourConn.onicecandidate = function (event) { 
            if (event.candidate) { 
               send({ 
                  type: "candidate", 
                  candidate: event.candidate 
               }); 
            } 
         }; 
			
      }, function (error) { 
         console.log(error); 
      }); 
		
   } 
};
 
//initiating a call 
callBtn.addEventListener("click", function () { 
   var callToUsername = callToUsernameInput.value; 
	
   if (callToUsername.length > 0) { 
      connectedUser = callToUsername; 
		
      // create an offer 
      yourConn.createOffer(function (offer) { 
         send({
            type: "offer", 
            offer: offer 
         }); 
			
         yourConn.setLocalDescription(offer); 
      }, function (error) { 
         alert("Error when creating an offer"); 
      }); 
   } 
});
 
//when somebody sends us an offer 
function handleOffer(offer, name) { 
   connectedUser = name; 
   yourConn.setRemoteDescription(new RTCSessionDescription(offer)); 
	
   //create an answer to an offer 
   yourConn.createAnswer(function (answer) { 
      yourConn.setLocalDescription(answer); 
		
      send({ 
         type: "answer", 
         answer: answer 
      });
		
   }, function (error) { 
      alert("Error when creating an answer"); 
   }); 
	
};
 
//when we got an answer from a remote user 
function handleAnswer(answer) { 
   yourConn.setRemoteDescription(new RTCSessionDescription(answer)); 
};
 
//when we got an ice candidate from a remote user 
function handleCandidate(candidate) { 
   yourConn.addIceCandidate(new RTCIceCandidate(candidate)); 
};
 
//hang up
hangUpBtn.addEventListener("click", function () { 
   send({ 
      type: "leave" 
   }); 
	
   handleLeave(); 
});
 
function handleLeave() { 
   connectedUser = null; 
   remoteAudio.src = null; 
	
   yourConn.close(); 
   yourConn.onicecandidate = null; 
   yourConn.onaddstream = null; 
};