I am developing a web application, like an online classroom in which I want to share the screen of a browser from a computer and view it in another. I am getting an error "Uncaught (in promise) DOMException: Error" in chrome when I tried to share the screen from a computer and view it on another computer.
I am using WebRTC for this and WebSocket for signaling. At the backend, java jersey would be doing the searching & forwarding of the request to the appropriate clients. I can share the screen from one browser window and view it in another on the same machine. But when I'm using different computers I get this error. When I debug the RTCPeerConnection object, it shows that the property connectionState as failed and iceConnectionState as disconnected.
Javascript: Request to share the screen
var urlS = [];
var config = {iceServers: urlS};
var $source = $('#monitor-src');
$scope.context.peerConnection = new RTCPeerConnection();
$scope.context.peerConnection.onicecandidate = function(event)
{
console.log(event)
if (event.candidate)
{
var json =
{
type:event.type,
label:event.candidate.sdpMLineIndex,
id:event.candidate.sdpMid,
candidate:event.candidate
}
WebSocket.send({desc:json,usrId:$scope.context.me.id},$scope)
}
else
{
console.error("Failed to create ice candidate")
}
};
try
{
$scope.context.peerConnection.createOffer({offerToReceiveAudio: true,offerToReceiveVideo: true}).then(function(offer)
{
return $scope.context.peerConnection.setLocalDescription(offer);
}).then(function()
{
WebSocket.send({desc:$scope.context.peerConnection.localDescription,callee:mentee.id,caller:$scope.context.me.id,usrId:$scope.context.me.id},$scope)
});
}
catch(error)
{
console.error("onnegotiationneeded-"+error)
}
$scope.context.peerConnection.onnegotiationneeded = function()
{
console.error("onnegotiationneeded")
};
try
{
console.log($scope.context.peerConnection);
$scope.context.peerConnection.ontrack = function(event)
{
console.log("ontrack:"+event.streams.length)
$source.parent()[0].srcObject= event.streams[0];
};
$scope.context.peerConnection.onaddstream = function(event)
{
console.log("onaddstream:"+event.stream)
$source.parent()[0].srcObject = event.stream;
};
}
catch(error)
{
console.error(error)
}
Javascript:WebSocket Handling of the request and sending response
$rootScope.socket.onMessage(function(message)
{
data = angular.fromJson(message.data);
if(data.type == 'offer')
{
var stream = null;
//var urlS = [{urls: 'stun:192.168.1.16:8443'}];
var urlS = [];
var config = {iceServers: urlS};
scope.context.peerConnection = new RTCPeerConnection();
scope.context.peerConnection.setRemoteDescription(data).then(function(){
return navigator.mediaDevices.getDisplayMedia({video:true,audio: true});
}).then(function(stream){
console.log(scope.context.peerConnection)
scope.context.peerConnection.addStream(stream);
stream.getTracks().forEach(function(track)
{
//var rtpSender =
});
scope.context.peerConnection.createAnswer().then(function(answer){
return scope.context.peerConnection.setLocalDescription(answer)
}).then(function()
{
send({desc:scope.context.peerConnection.localDescription,usrId:scope.context.me.id},scope)
}).catch(function(error){
console.error(error)});
})
}
else if(data.type == 'answer')
{
scope.context.peerConnection.setRemoteDescription(data);
}
else if(data.type == 'icecandidate')
{
console.log("icecandidate:"+angular.toJson(data))
var promise = scope.context.peerConnection.addIceCandidate(data.candidate).then(function success(){
console.log("ice success")
}).catch(function error(err)
{
console.log(err);
});
}
});
};
The ontrack and onaddstream events are triggered when a stream is added to the peer connection. But I get nothing on the requested peer.
I am not a JavaScript expert but your urlS array seems to be empty. Try to add both Turn and Stun servers in your urlS.
For more info take a look here
I'm trying to learn WebSockets and I've created a websocket server in Node and am now working on the browser implementation. I have tested that the server works and responds how I want using a chrome extension called Smart WebSocket Client.
The console in the browser says Button pressed! when you press the button and Connection lost! (1000) when I end the Node process but never has it said Connection Established!.
Edit: The client code is running on a site secured with HTTPS and that serves the HSTS header while the server code (currently, but won't continue to be) is running on localhost over normal HTTP, if it's any concern.
Server Code:
const websock = require('./node_modules/ws');
const HashMap = require('./node_modules/hashmap');
const jsonparse = require('./node_modules/jsonparse');
const randomstring = require('./node_modules/randomstring');
class Session {
constructor(server) {
this.server = server;
this.clients = [];
}
}
var connections = new HashMap();
const json = new jsonparse();
const wss = new websock.Server({ port: 36245 });
process.on('SIGINT',function () {
console.log("Recieved SIGINT, stopping gracefully...");
wss.clients.forEach(function (ws) {
console.log("-Ended connection with "+ws.upgradeReq.socket.remoteAddress+" (1001)");
ws.closeReasonCode = 1001;
ws.close();
});
process.exit(1);
});
wss.on('connection',function connection(ws,conn) {
console.log("+Recieved connection from "+ws._socket.remoteAddress);
ws.upgradeReq = conn;
ws.hasHandshook = false;
ws.onmessage = function message(msg) {
var message;
try {
message = JSON.parse(msg.data);
} catch (ex) {
ws.send("{\"e\":\"Invalid json.\"}");
return;
}
if (!ws.hasHandshook) {
ws.hasHandshook = true;
if (message.type === "client") {
//ensure code was provided and has a room
if (typeof message.code === 'undefined' || !connections.has(message.code)) {
ws.send("{\"e\":\"Invalid game code.\"}");
ws.closeReasonCode = 4001;
ws.closeDescription = "Invalid game code.";
console.log("-Ended connection with "+ws._socket.remoteAddress+ " (4001)");
ws.close();
}
if (typeof message.name === 'undefined') {
//TODO error out, no player name provided
}
//attach client to game session
ws.clientType = "client";
ws.gameCode = message.code;
ws.playerName =
connections.get(message.code).clients.add(ws);
ws.send("{\"joingame\":\"true\"}");
} else {
ws.send("{\"e\":\"Invalid type provided on handshake message.\"}");
ws.closeReasonCode = 4000;
ws.closeDescription = "Invalid type provided on handshake message.";
console.log("-Ended connection with "+ws._socket.remoteAddress+" (4000)");
ws.close();
}
}
};
ws.onclose = function close() {
console.log("-Ended connection with "+ws.upgradeReq.socket.remoteAddress+" (Client Closed)");
}
});
Client Code, which is successfully run on the press of a button on the page:
function DoJoinGame () {
console.log("Button pressed!");
gameCode = document.getElementById('base-gameCode').value.toUpperCase();
playerName = document.getElementById('base-playerName').value;
var ws = new WebSocket("ws://localhost:36245");
ws.onopen = function (event) {
console.log("Connection Established!");
ws.send("{\"type\":\"client\",\"code\":\""+gameCode+"\",\"name\":\""+playerName+"\"");
};
ws.onmessage = function (msg) {
let message = JSON.parse(msg.data);
if (message.joingame) { //if this is a "client added to session" message, set display: none; on the codeEntry div
document.getElementById('codeEntry').style.display = "none";
}
//TODO handle message
};
ws.onclose = function (evt) {
console.log("Connection lost! ("+evt.code+":"+evt.reason+")");
};
}
Thank you for your help!
Problem fixed. I was attempting to connect to a non secure websocket server from a secure origin and chrome & co. wasn't a fan.
I have very simple code, yet, it doesn't work perfectly.
In Java server it just says Hello and Bye when opening and closing a connection and prints a sent message:
#ApplicationScoped
#ServerEndpoint("/tictactoe")
public class WebSocketServer {
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void open(Session session) {
logger.info("WebSocket: Hello - " + session.getId());
}
#OnClose
public void close(Session session) {
logger.info("WebSocket: Farewell - " + session.getId());
}
#OnMessage
public void messageHandler(String message, Session session) {
logger.info("WebSocket: New Message - " + message);
}
}
In JavaScript it does pretty much the same like in the server and sends a message when clicking a button:
var socket = new WebSocket("ws://localhost:8080/TicTacToeZTP/tictactoe");
socket.onopen = function (event) {
console.log("WebSocket: Connected");
console.log("WebSocket: " + checkConnection(socket.readyState));
};
socket.onclose = function (event) {
console.log("WebSocket: Disconnected");
};
socket.onerror = function(event) {
console.log("WebSocket: Error");
};
socket.onmessage = function (event) {
console.log("WebSocket: New Message - " + event.data);
};
function checkConnection(readyState) {
switch(readyState){
case 0: return "CONNECTING";
case 1: return "OPEN";
case 2: return "CLOSING";
case 3: return "CLOSED";
default: return "UNDEFINED";
}
}
$("#send").click(function () {
var msg = {
type: "message",
text: "zaladzi"
};
socket.send(JSON.stringify(msg));
});
Now its time for a problem. After refreshing a page with an established connection.
What the script says:
WebSocket: Connected
WebSocket: OPEN
But the server doesn't open a new one. In fact I sometimes need a couple of refreshes to open a new connection on the server.
What the server says:
Info: WebSocket: Hello - 29538711-f815-4c59-835e-97aaaac1d112
Info: WebSocket: Farewell - 29538711-f815-4c59-835e-97aaaac1d112
I'm using Payara 4.1 server. How to solve this issue?
TL/DR JavaScript client says connection is opened, but Java client says there is no such a connection.
This is likely due to a bug in Payara Server which is fixed https://github.com/payara/Payara/issues/536 in that bug OnOpen isn't called in the server when a socket is reused.
You could try a pre-release version of Payara to ensure it is fixed. Pre-release builds are available from the Payara website a new pre-release build is created and uploaded every time their Jenkins CI server completes a GitHub merge build.
The intent is for this to become a Community Wiki post that is kept up-to-date so developers interested in implementing communication of JSON messages browser-to-browser (p2p) with WebRTC DataChannels have simple yet functional examples.
WebRTC DataChannels are experimental and still in draft. It seems that currently the web is a minefield of outdated WebRTC examples and even more so if a developer is trying to learn the RTCDataChannel API.
Simple yet functional 1-page examples that work today across WebRTC compliant browsers seem very difficult to find. For example, some examples leave out a signaling implementation, others only work for a single browser (e.g. Chrome-Chrome), many are outdated due to recent API changes, and others are so complex they create a barrier to getting started.
Please post examples that meet the following criteria (if something is not met please specify):
Client-side code is 1-page (200 lines or less)
Server-side code is 1-page and technology is referenced (e.g. node.js, php, python, etc.)
Signaling mechanism is implemented and protocol technology is referenced (e.g. WebSockets, long polling, GCM, etc.)
Working code that runs cross-browser (Chrome, Firefox, Opera, and/or Bowser)
Minimal options, error handling, abstraction, etc. -- the intent is an elementary example
Here is a working example that uses HTML5 WebSockets for signaling and a node.js backend
signaling technology: WebSockets
client: pure html/javascript
server: node.js, ws
last tested on: Firefox 40.0.2, Chrome 44.0.2403.157 m, Opera 31.0.1889.174
client-side code:
<html>
<head>
</head>
<body>
<p id='msg'>Click the following in different browser windows</p>
<button type='button' onclick='init(false)'>I AM Answerer Peer (click first)</button>
<button type='button' onclick='init(true)'>I AM Offerer Peer</button>
<script>
(function() {
var offererId = 'Gandalf', // note: client id conflicts can happen
answererId = 'Saruman', // no websocket cleanup code exists
ourId, peerId,
RTC_IS_MOZILLA = !!window.mozRTCPeerConnection,
RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.msRTCPeerConnection,
RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.msRTCSessionDescription,
RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.msRTCIceCandidate,
rtcpeerconn = new RTCPeerConnection(
{iceServers: [{ 'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]},
{optional: [{RtpDataChannels: false}]}
),
rtcdatachannel,
websocket = new WebSocket('ws://' + window.location.hostname + ':8000'),
comready, onerror;
window.init = function(weAreOfferer) {
ourId = weAreOfferer ? offererId : answererId;
peerId = weAreOfferer ? answererId : offererId;
websocket.send(JSON.stringify({
inst: 'init',
id: ourId
}));
if(weAreOfferer) {
rtcdatachannel = rtcpeerconn.createDataChannel(offererId+answererId);
rtcdatachannel.onopen = comready;
rtcdatachannel.onerror = onerror;
rtcpeerconn.createOffer(function(offer) {
rtcpeerconn.setLocalDescription(offer, function() {
var output = offer.toJSON();
if(typeof output === 'string') output = JSON.parse(output); // normalize: RTCSessionDescription.toJSON returns a json str in FF, but json obj in Chrome
websocket.send(JSON.stringify({
inst: 'send',
peerId: peerId,
message: output
}));
}, onerror);
}, onerror);
}
};
rtcpeerconn.ondatachannel = function(event) {
rtcdatachannel = event.channel;
rtcdatachannel.onopen = comready;
rtcdatachannel.onerror = onerror;
};
websocket.onmessage = function(input) {
var message = JSON.parse(input.data);
if(message.type && message.type === 'offer') {
var offer = new RTCSessionDescription(message);
rtcpeerconn.setRemoteDescription(offer, function() {
rtcpeerconn.createAnswer(function(answer) {
rtcpeerconn.setLocalDescription(answer, function() {
var output = answer.toJSON();
if(typeof output === 'string') output = JSON.parse(output); // normalize: RTCSessionDescription.toJSON returns a json str in FF, but json obj in Chrome
websocket.send(JSON.stringify({
inst: 'send',
peerId: peerId,
message: output
}));
}, onerror);
}, onerror);
}, onerror);
} else if(message.type && message.type === 'answer') {
var answer = new RTCSessionDescription(message);
rtcpeerconn.setRemoteDescription(answer, function() {/* handler required but we have nothing to do */}, onerror);
} else if(rtcpeerconn.remoteDescription) {
// ignore ice candidates until remote description is set
rtcpeerconn.addIceCandidate(new RTCIceCandidate(message.candidate));
}
};
rtcpeerconn.onicecandidate = function (event) {
if (!event || !event.candidate) return;
websocket.send(JSON.stringify({
inst: 'send',
peerId: peerId,
message: {candidate: event.candidate}
}));
};
/** called when RTC signaling is complete and RTCDataChannel is ready */
comready = function() {
rtcdatachannel.send('hello world!');
rtcdatachannel.onmessage = function(event) {
document.getElementById('msg').innerHTML = 'RTCDataChannel peer ' + peerId + ' says: ' + event.data;
}
};
/** global error function */
onerror = websocket.onerror = function(e) {
console.log('====== WEBRTC ERROR ======', arguments);
document.getElementById('msg').innerHTML = '====== WEBRTC ERROR ======<br>' + e;
throw new Error(e);
};
})();
</script>
</body>
</html>
server-side code:
var server = require('http').createServer(),
express = require('express'),
app = express(),
WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ server: server, port: 8000 });
app.use(express.static(__dirname + '/static')); // client code goes in static directory
var clientMap = {};
wss.on('connection', function (ws) {
ws.on('message', function (inputStr) {
var input = JSON.parse(inputStr);
if(input.inst == 'init') {
clientMap[input.id] = ws;
} else if(input.inst == 'send') {
clientMap[input.peerId].send(JSON.stringify(input.message));
}
});
});
server.on('request', app);
server.listen(80, YOUR_HOSTNAME_OR_IP_HERE, function () { console.log('Listening on ' + server.address().port) });
i want to build an architecture with wss, i implement my certificates and they work. But now, when i'm connect on the browser, my program create websocket and close it directly, i don't understand why, this is my code which is running at port 5005
window.onload=function(){
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if (window.WebSocket) {
socket = new WebSocket("wss://localhost:7575/websocket");
socket.onopen = function(){
alert("opened the connection");
socket.send("Hello");
};
socket.onmessage = function(message){
var json = jQuery.parseJSON(message.data);
notifyApplication(json);
};
socket.onclose=function(){
alert("Websocket coonection is closed");
};
}
else {
alert("Your browser doesn't support websocket");
}
};
and the webscoket server is implemented using netty and it is running at the port 7575.
which offers an SSL3.0 enabled https connection.