I am trying to build video chat but unable to understand some piece of code:
I have Found that part of Code From WEBRTC Sample
link:-https://github.com/webrtc/samples/commit/ecca1124803688bf512874188624f6d4538f69d0
var servers = null;
pc1 = new RTCPeerConnection(servers);
trace('Created local peer connection object pc1');
pc1.onicecandidate = function(e) {
onIceCandidate(pc1, e);
};
pc2 = new RTCPeerConnection(servers);
trace('Created remote peer connection object pc2');
pc2.onicecandidate = function(e) {
onIceCandidate(pc2, e);
};
pc1.oniceconnectionstatechange = function(e) {
onIceStateChange(pc1, e);
};
pc2.oniceconnectionstatechange = function(e) {
onIceStateChange(pc2, e);
};
pc2.ontrack = gotRemoteStream;
What is happening when I am passing null value to RTCPeerConnection()?
The constructor RTCPeerConnection accepts a configuration object. Among other things, one of the configurations required by most apps would be iceServers.
iceServers is a list of STUN or TURN servers. For example, your constructor could look like:
var configuration = {
"iceServers": [{ "urls": ["stun:stun.1.google.com:19302"] }]
};
myConnection = new RTCPeerConnection(configuration);
In simple words these STUN and TURN servers help the two peers discover a direct path to each other. However when you leave out the servers, it means the app will be able to discover the peer only within the intranet, or essentially within the set of devices that your computer can interact directly with. [Citation Needed]
In any production app, you would most likely have to add the STUN and TURN servers. But since you are referring to the code from a tutorial, where connection across internet is not required, you can skip the servers.
Related
We are unable get the public IP address of a client machine. It is showing the sdp is undefined while executing the code. Below is the code.
Get current IP in JS (no third party services)
https://github.com/diafygi/webrtc-ips
//get the IP addresses associated with an account
function getIPs(callback){
var ip_dups = {};
//compatibility for firefox and chrome
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var useWebKit = !!window.webkitRTCPeerConnection;
//bypass naive webrtc blocking using an iframe
if(!RTCPeerConnection){
//NOTE: you need to have an iframe in the page right above the script tag
//
//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
//<script>...getIPs called in here...
//
var win = iframe.contentWindow;
RTCPeerConnection = win.RTCPeerConnection
|| win.mozRTCPeerConnection
|| win.webkitRTCPeerConnection;
useWebKit = !!win.webkitRTCPeerConnection;
}
//minimal requirements for data connection
var mediaConstraints = {
optional: [{RtpDataChannels: true}]
};
var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
//construct a new RTCPeerConnection
var pc = new RTCPeerConnection(servers, mediaConstraints);
function handleCandidate(candidate){
//match just the IP address
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
var ip_addr = ip_regex.exec(candidate)[1];
//remove duplicates
if(ip_dups[ip_addr] === undefined)
callback(ip_addr);
ip_dups[ip_addr] = true;
}
//listen for candidate events
pc.onicecandidate = function(ice){
//skip non-candidate events
if(ice.candidate)
handleCandidate(ice.candidate.candidate);
};
//create a bogus data channel
pc.createDataChannel("");
//create an offer sdp
pc.createOffer(function(result){
//trigger the stun server request
pc.setLocalDescription(result, function(){}, function(){});
}, function(){});
//wait for a while to let everything done
setTimeout(function(){
//read candidate info from local description
var lines = pc.localDescription.sdp.split('\n');
lines.forEach(function(line){
if(line.indexOf('a=candidate:') === 0)
handleCandidate(line);
});
}, 1000);
}
//Test: Print the IP addresses into the console
getIPs(function(ip){console.log(ip);});
While executing the code we are getting this error message:
'Cannot read property 'sdp' of null'
The example code you are referencing is outdated and their demo page is no longer working either on recent Chrome versions:
https://diafygi.github.io/webrtc-ips/
Furthermore, it seems to use features that are not supported by some browsers.
I don't know your requirements but it is quite standard to send a request to a server in order to discover the public IP of a client. The server looks at headers (e.g. x-forwarded-for, this depends on the Web server used) and sends it back to the requester.
There also exist services such as Ipregistry (disclaimer: I run the service) that do it for you and return even more interesting information: client IP address, location, currency, threat data, etc.
As of this writing, you cannot leak the private IP address of your users.
However, I found a github repo webrtc-ip which can leak a user's public IP address using WebRTC. This is powerful because you cannot trace it, as nothing is shown in the Networks tab.
Sadly, this leak does not work for private IPs, due to the gradual shift to mDNS (at least for WebRTC), which is completely in this great blog. Regardless, here's a working demo:
https://webrtc-ip.herokuapp.com/
I am not sure if this leaks your true IP address regardless of a proxy, but feel free to test it out.
If you look at the repo you referenced, the issues clearly state that the repo does not work and that the repository is not being maintained.
I had built interception calls in the socket.io file located under node_modules/socket.io/lib/client.js with version 1.3.7 (at least I think so, however I have to update to 1.4.5 because of other requirements). These changes allowed spoof information coming from the sender socket and they were done before continuing to send the data to the receiver socket.
Before (around 1.3.7), the method ran before sending a packet was the following:
Client.prototype.packet = function(packet, preEncoded, volatile){
var self = this;
var sockets = this.sockets[0]; //this helds the socket object
but now (1.4.5) socket.io changed its call to the following
Client.prototype.packet = function(packet, opts){
var sockets = this.sockets[0]; //gives undefined
I tried to look throughout the given objects but couldn't find the sockets of the receiver user.
Back in 1.3.7 I was able to effortlessly give properties to a socket object (e.g: socket.some-property = 1; in the .js file ran by nodejs in the root of the server) and later be able to get this some-property back in node_modules/client.js whenever the receiver got some packet so I could intercept the call but now it does not work and I would like to apply my old code to this new context in order for it all to function again.
var socketObject = {};
io.sockets.on('connection', function (client) {
socketObject[client.id] = {socket: client};
client.on('data', function (somedata) {
socketObject[client.id].data = someData;
});
client.on('disconnect', function() {
delete socketObject[client.id];
});
});
I have recently developed a web app using PeerJS, and am trying to add reconnect functionality.
Basically, my app works by someone creating a server that clients then connect to. The server person can control what the hosts are doing but its basic two way communication.
If a client disconnects they simply reconnect and it works normally. However if the server user refreshes the page, or their computer crashes then they need to be able to re-establish control over the clients.
The start of this is by regaining the original connection ID and peer api ID, which is fine and easy as they are stored in a database and assigned a unique ID the server user can use to query them. Then to enable the client to reconnect I do this upon close:
// connection is closed by the host involuntarily...
conn.on('close', function() {
// if the clients connection closes set up a reconnect request loop - when the host takes back control
// the client will auto reconnect...
connected = false;
conn = null;
var reconnect_timer = setInterval(function () {
console.log('reconnecting...'); // make a fancy animation here...
conn = peer.connect(connectionid, {metadata: JSON.stringify({'type':'hello','username':username})});
// upon connection
conn.on('open', function() { // if this fails need to provide an error message... DO THIS SOON
// run the connect function...
connected = true;
connect(conn);
});
// didnt connect yet
conn.on('error', function(err) {
connected = false;
});
if(connected === true) {
clearInterval(reconnect_timer);
}
}, 1000);
});
This appears to work, as on the server end the client looks like they have reconnected - the connect function has fired etc. However messages cant be sent between, and the client console says:
Error: Connection is not open. You should listen for the `open` event before sending messages.(…)
Where the 'open' event is shown as having been listened to above...
I hope this is clear - any help is appreciated :)
So in the end to create an auto reconnect script, I simply dealt with the client end of things, ensuring the server was set to the same api_key (for cloudservers) and key:
peer = new Peer(return_array.host_id, {key: return_array.api_key});
and then having the client, upon connection closing:
// connection is closed by the host involuntarily...
conn.on('close', function() {
// if the clients connection closes set up a reconnect request loop - when the host takes back control
// the client will auto reconnect...
peer.destroy(); // destroy the link
connected = false; // set the connected flag to false
conn = null; // destroy the conn
peer = null; // destroy the peer
// set a variable which means function calls to launchPeer will not overlap
var run_next = true;
// periodically attempt to reconnect
reconnect_timer = setInterval(function() {
if(connected===false && run_next===true) {
run_next = false; // stop this bit rerunning before launchPeer has finished...
if(launchPeer(false)===true) {
clearInterval(reconnect_timer);
} else run_next == true;
}
}, 1000);
});
Where launch peer will attempt to launch a new peer. To ensure continuity the new id from the client replaces the old id from the client and everything is a smooth takeover. The hardest part in the end was having the "setInterval" only fire once which is achieved (badly...) through use of boolean flags.
Thanks to anybody who read and thought how they could help :)
How can I get the local client IP using WebRTC.
I don't need the REMOTE_ADDR of the client but his local network IP.
I've seen this before on websites like sharedrop.com, it recognizes computer within the same network using WebRTC.
In PHP I do this to get the clients remote IP:
<?php
echo $_SERVER["REMOTE_ADDR"]; // which would return 72.72.72.175
?>
I looked through stackoverflow but every question is answered using the remote addr.
How can I get my local IP (192.168.1.24 for example) with JavaScript instead of the remote addr.
UPDATE
Unfortunately the below answer no longer works as browsers have changed this behavior due to security concerns. See this StackOverflow Q&A for more details.
where I took code from --> Source
You can find a demo at --> Demo
I have modified the source code, reduced the lines, not making any stun requests since you only want Local IP not the Public IP, the below code works in latest Firefox and Chrome:
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
pc.createDataChannel(""); //create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop); // create offer and set local description
pc.onicecandidate = function(ice){ //listen for candidate events
if(!ice || !ice.candidate || !ice.candidate.candidate) return;
var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
console.log('my IP: ', myIP);
pc.onicecandidate = noop;
};
what is happening here is, we are creating a dummy peer connection, and for the remote peer to contact us, we generally exchange ice candidates with each other. And reading the ice candiates we can tell the ip of the user.
You can use this version on modern browser (with Promises and async / await)
// minified onliner, 219b
const ip = await new Promise((s,f,c=new RTCPeerConnection(),k='candidate')=>(c.createDataChannel(''),c.createOffer(o=>c.setLocalDescription(o),f),c.onicecandidate=i=>i&&i[k]&&i[k][k]&&c.close(s(i[k][k].split(' ')[4]))))
Or, un-minified:
// cleaned, 363b
const ip = await new Promise((resolve, reject) => {
const conn = new RTCPeerConnection()
conn.createDataChannel('')
conn.createOffer(offer => conn.setLocalDescription(offer), reject)
conn.onicecandidate = ice => {
if (ice && ice.candidate && ice.candidate.candidate) {
resolve(ice.candidate.candidate.split(' ')[4])
conn.close()
}
}
})
I'm experimenting with WebRTC between two browsers using RTCPeerConnection and my own long-polling implementation. I've created demo application, which successfully works with Mozilla Nightly (22), however in Chrome (25), I can't get no remote video and only "empty black video" appears. Is there something wrong in my JS code?
Function sendMessage(message) sends message to server via long-polling and on the other side, it is accepted using onMessage()
var peerConnection;
var peerConnection_config = {"iceServers": [{"url": "stun:23.21.150.121"}]};
// when message from server is received
function onMessage(evt) {
if (!peerConnection)
call(false);
var signal = JSON.parse(evt);
if (signal.sdp) {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp));
} else {
peerConnection.addIceCandidate(new RTCIceCandidate(signal.candidate));
}
}
function call(isCaller) {
peerConnection = new RTCPeerConnection(peerConnection_config);
// send any ice candidates to the other peer
peerConnection.onicecandidate = function(evt) {
sendMessage(JSON.stringify({"candidate": evt.candidate}));
};
// once remote stream arrives, show it in the remote video element
peerConnection.onaddstream = function(evt) {
// attach media stream to local video - WebRTC Wrapper
attachMediaStream($("#remote-video").get("0"), evt.stream);
};
// get the local stream, show it in the local video element and send it
getUserMedia({"audio": true, "video": true}, function(stream) {
// attach media stream to local video - WebRTC Wrapper
attachMediaStream($("#local-video").get("0"), stream);
$("#local-video").get(0).muted = true;
peerConnection.addStream(stream);
if (isCaller)
peerConnection.createOffer(gotDescription);
else {
peerConnection.createAnswer(gotDescription);
}
function gotDescription(desc) {
sendMessage(JSON.stringify({"sdp": desc}));
peerConnection.setLocalDescription(desc);
}
}, function() {
});
}
My best guess is that there is a problem with your STUN server configuration. To determine if this is the issue, try using google's public stun server stun:stun.l.google.com:19302 (which won't work in Firefox, but should definitely work in Chrome) or test on a local network with no STUN server configured.
Also, verify that your ice candidates are being delivered properly. Firefox doesn't actually generate 'icecandidate' events (it includes the candidates in the offer/answer), so an issue with delivering candidate messages could also explain the discrepancy.
Make sure your video tag attribute autoplay is set to 'autoplay'.