ICE candidates gathered only from one network interface - webrtc

Got very simple code:
<script type="text/javascript">
pc = new window.RTCPeerConnection();
pc.onicecandidate = function(event) {
console.log("onicecandidate\n", event);
}
pc.onicegatheringstatechange = function(event) {
console.log("onicegatheringstatechange\n", event);
}
dc = pc.createDataChannel("dataChannel");
errFunc = function(err) {
console.log("errFunc\n", err);
}
successCback = function() {
console.log("setLocalDescription is a success\n");
}
pc.createOffer()
.then(function(offer) { pc.setLocalDescription(offer)})
.then(successCback)
.catch(errFunc);
</script>
Got ubuntu running chromium and TWO local ethernet interfaces.
Running aforementioned code yields only 1 call to onicecandidate and
1 call to onicegatheringstatechange. (any STUN/TURN servers are deliberately not specified, so I do expect only local host candidates, but from all interfaces). Only one ethernet interface is examined by ICE.
Why ?

Unless you have permissions for getUserMedia, Chrome will restrict ICE candidates to the interface of the default route. The rationale is explained in this draft

Related

ICE failed on firefox but peerJs's exemple work fine

I try to make a simple chat with peerJs to learn how to use peer to peer
when I try to connect two clients, this error happens on both client
WebRTC: ICE failed, your TURN server appears to be broken, see about:webrtc for more details
PeerJS: iceConnectionState is failed, closing connections
the peerJs demo work fine on Firefox (even when i run it locally)
and my code seem to work correctly on edge
I try in private with disabled add-on
my media.peerconnection.ice.proxy_only is set to false.
Any setting related to ice or peer is set to default
My code
both client have the same code, they try to connect to the client in the url
exemple:
i open http://localhost:5173/room who get an peerId and rename itselfhttp://localhost:5173/room?roomId=198ec396-1691-48cf-b6ea-16d2102c4917 then i copy paste this link to another tab
<script lang="ts">
import { page } from '$app/stores';
import { Peer } from 'peerjs';
import { onMount } from 'svelte';
let peer: Peer;
onMount(() => {
const url = $page.url.searchParams;
peer = new Peer({ debug: 3 });
peer.on('open', function (id) {
console.log('open| id :', id);
if (url.has('roomId')) {
let conn = peer.connect(url.get('roomId')!, {
reliable: true
});
conn.on('open', function () {
console.log('test 1');
conn.send('test send 1');
});
}
// change url to be easily copied
window.history.replaceState({}, '', 'room?roomId=' + id);
});
peer.on('connection', function (connexion) {
console.log('test 2');
connexion.send('test send 2');
});
});
</script>
firefox log
edge log (seem to connect but test's send() not logged)

Is there a way to multi browser communicate each other without peers?still able to communicate after lose peers connecting?

Is there a way to multi browser communicate each other without peers?or still able to communicate after lose peers connecting?
I created sample with gun.js like below:
server.js:
const express = require('express')
const Gun = require('gun')
const app = express()
const port = 8000
app.use(Gun.serve)
const server = app.listen(port, () => {
console.log("Listening at: http://localhost://" + port)
})
Gun({web: server})
test.ts on angular demo:
gun = GUN({
peers: ['http:localhost:8000/gun']
});
data: any;
initDate(): void {
this.gun.get('mark').put({
name: "Mark",
email: "mark#gun.eco",
});
}
listenDate(): void {
this.gun.get('mark').on((data, key) => {
console.log("realtime updates:", data);
this.data = data;
});
}
submit(): void {
this.gun.get('mark').get('live').put(Math.random());
}
I start server.js as a peer and start angular app,open two broswer with same url,the two broswer communicate well.
but after i stop server.js , the two broswer are unable to communicate each other.
Is there a way to the two browser communicate each other without server.js?or how still able to communicate after I stop server.js?

Chrome on Android not connecting to peer over WebRTC

I'm building a WebRTC app with a central electron app that browsers connect to. The scenario I'm testing is running the electron app on my computer (Ubuntu 16.04) and connecting from chrome (69) on Android (7.0). Following the debugging the offer, answer and candidate are passed, but fails on the last stop of generating the connection. The ice connection state switchs to "checking" then "failed". I'm able to load the browser app on my laptop and connect to an electron app on the same computer.
Should I be using a collection of ice servers? What do I need to make the WebRTC connection more robust? Should I not write my own signaling process and use something pre-made? Is their anyway to debug the reason why the connection failed? For debugging I've tried the webrtc debugging tab on chrome but all it says is connection failled at the bottom of the stack.
The configuration for my RTCPeerConnection is:
const configuration = {
"iceServers": [{ "urls": "stun:stun.1.google.com:19302" }]
};
This is the code I use to form iniate the connection to the electron app from the browser app (The function are attached to a ts class which are called in order: setupPeerConnection, setupDataChannel, makeOffer):
setupPeerConnection(gameID:string) {
this.gameID = gameID;
let configuration:RTCConfiguration = {
"iceServers": [{ "urls": "stun:stun.1.google.com:19302" }]
};
this.connection = new RTCPeerConnection(configuration);
const that:PeerConnection = this;
//Definition of the data channel
this.connection.ondatachannel = function(ev:RTCDataChannelEvent) {
};
//When we get our own ICE Candidate, we provide it to the other Peer.
this.connection.onicecandidate = function(event:RTCPeerConnectionIceEvent) {
if (event.candidate && that.connectedToGame) {
that.serverConnection.send({
type: "candidate",
candidate: event.candidate
});
}
};
this.connection.oniceconnectionstatechange = function(e:Event) {
let iceState:RTCIceConnectionState = this.iceConnectionState;
console.log("Changing connection state:", iceState)
if (iceState == "connected") {
console.log("Connection established with server");
} else if (iceState =="disconnected" || iceState == "closed") {
// We lost the user
that.connectedToGame = false;
that.onLeave();
}
};
}
setupDataChannel(onopen:(error:ErrorEvent)=>void, onmessage:(message:MessageEvent)=>void) {
let dataChannelOptions:RTCDataChannelInit = <RTCDataChannelInit>{
reliable: true
};
this.dataChannel = this.connection.createDataChannel(this.gameID + "-dataChannel", dataChannelOptions);
this.dataChannel.onerror = function (error:ErrorEvent) {
console.log("Error on data channel:", error);
};
this.dataChannel.onmessage = onmessage.bind(this);
this.dataChannel.onopen = onopen;
this.dataChannel.onclose = function() {
console.log("Channel closed.");
};
}
makeOffer() {
let that:PeerConnection = this;
this.connection.createOffer().then(function (offer:RTCSessionDescriptionInit) {
that.serverConnection.send({
gameID: that.gameID,
type: "offer",
offer: offer
});
that.connection.setLocalDescription(offer);
}, function (error) {
console.log("Error contacting remote peer: ", error);
});
}

Can't createAnswer from peer

I'm facing a problem where createAnswer() is not being called.
I'm looking for a way where a new user connects to the website and all other peers get an offer from the new peer and should create an answer. Where is my problem?
function onMessage (topic, event) {
console.log(event);
if(event.session_id == session._session_id)
return;
if(event.sdp) {
console.log(event.sdp.type);
if(event.type == "offer"){
pc.setRemoteDescription(new RTCSessionDescription(event.sdp));
pc.createAnswer(function(offer) {
debugger;
pc.setLocalDescription(offer);
session.publish("http://example.com/webrtc", { session_id: session._session_id ,sdp: offer, type: offer.type});
});
}
}
if(event.candidate)
pc.addIceCandidate(new RTCIceCandidate(event.candidate));
}
For the signalling channel I use Web-sockets an the wamp protocol.
I have deployed the application here,
the source code is available here.

Generating ICE Candidates

I am working WebRTC API's to make a video call between two PC's running on chrome browser. My observation is ICE Candidates are generated only if i connected to internet else no ice candidates are generated. Why is it like that?
connection block
var pc_config = {"iceServers":[]};
pc = new webkitRTCPeerConnection(pc_config);
pc.onicecandidate=function (evt) {
if(evt.candidate){
console.log("Sending candidate to other peer"+evt);
jWebSocketClient.broadcastText("",evt);
}
};
Thanks,
Sureshkumar Menon
As far as I understand, there is four types of ICE candidate :
Host candidate : from your local interface.
Server reflexive candidate : provided by the STUN server, a translation of your local address into public network.
Relayed candidate : provided by a TURN server, data will be relayed by the server
Peer reflexive candidate : a rare case (?) where candidate is discovered during the connectivity checks. I'll skip this part as it is quite rare and I'm not sure to understand the big picture of it.
If you don't provide any STUN / TURN addresses to your program or if they are unreachable, the only candidate which can be retrieved is the host one. Note that your local address (127.0.0.1) is not taken as a potential candidate.
Hope it helps.
However, I'm not totally sure to understand your use case.. Are both computers on the same local network ? If your interface is up, you should get at least the host candidate. I only worked with the C++ API, but I don't see why it would have a different behavior with the Javascript's.
If I'm not mistaken, ICE Candidates are created by contacting a STUN server, thus you need internet connection. This is done to translate a private address into a public one to enable your clients to connect (and be connected) to other clients.
Yes you have to connect to internet before your pcs share SDP. This is because ICE Server is not on your local computers but on the internet. The ICE server is connected in the WEB RTC in this line:
if (browser === 'firefox') {
PeerConnConfig = {
iceServers: [{
url: "stun:23.21.150.121" // FF doesn't support resolving DNS in iceServers yet
}
]
};
mediaConstraints = {
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true,
MozDontOfferDataChannel: true // Tell FF not to put datachannel info in SDP or chrome will crash
}
};
// FF doesn't expose this yet
MediaStream.prototype.getVideoTracks = function () {
return [];
};
MediaStream.prototype.getAudioTracks = function () {
return [];
};
} else {
PeerConnConfig = {
iceServers: [{
url: "stun:stun.l.google.com:19302"
}
]
};
mediaConstraints = {
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
},
optional: [{
DtlsSrtpKeyAgreement: true
}
]
};
// API compat for older versions of chrome
if (!MediaStream.prototype.getVideoTracks) {
MediaStream.prototype.getVideoTracks = function () {
return this.videoTracks;
};
MediaStream.prototype.getAudioTracks = function () {
return this.audioTracks;
};
}
if (!PeerConnection.prototype.getLocalStreams) {
PeerConnection.prototype.getLocalStreams = function () {
return this.localStreams;
};
PeerConnection.prototype.getRemoteStreams = function () {
return this.remoteStreams;
};
}
}
I cut above code from WEBRTC_SHIM. consider especially line that defines the ICE server as: url: "stun:stun.l.google.com:19302".