Websockets over WSS:// doesn't appear to fire events on server - javascript

I am trying to set up a basic WSS websockets server. This is my minimal HTML (with the embedded javascript):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body style="background-color:white">
<h1>Test of WSS server</h1>
<p>Status: <span id=status"></span></p>
Click to send message
<script src="/newjs/jquery-2.1.1.js"></script>
<script>
var connection;
$(document).ready(function () {
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
alert("browser says no");
console.log("Browser does not supports websockets");
return;
}
setupConnection();
});
function message() {
var msg = "Test Message";
connection.send(msg);
}
function setupConnection() {
connection = new WebSocket('wss://www.example.com:14000');
connection.onerror = function(error) {
console.log('onerror fired');
};
connection.onopen = function(event) {
$("#status").html("Open");
};
connection.onmessage = function (message) {
alert(message.data);
};
}
setInterval(function() {
if (connection.readyState !== 1) {
setupConnection();
}
}, 5000);
</script>
</body>
</html>
The following is the JS server run by nodejs:
var fs=require("fs");
var ws_cfg = {
ssl: true,
port: 14000,
ssl_key: '/httpd/conf/ssl.key/my.key',
ssl_cert: '/httpd/conf/ssl.crt/my.crt',
ca_cert: '/httpd/conf/ssl.crt/gd_bundle-g2-g1.crt'
};
var processRequest = function(req, res) {
console.log("Request received.")
};
var httpServ = require('https');
var app = null;
app = httpServ.createServer({
key: fs.readFileSync(ws_cfg.ssl_key),
cert: fs.readFileSync(ws_cfg.ssl_cert),
ca: fs.readFileSync(ws_cfg.ca_cert),
},processRequest).listen(ws_cfg.port);
var WebSocketServer = require('ws').Server, ws_server = new WebSocketServer( {server: app});
ws_server.on('open',function(request) {
console.log("opening");
});
ws_server.on('request', function(request) {
console.log((new Date()) + ' Connection from origin ' + request.origin + '.');
if (request.origin!='https://www.example.com') {
console.log("rejecting request from " + request.origin + " as not coming from our web site");
return;
}
var connection = request.accept(null, request.origin);
connection.on('message', function(message) {
console.log("Got a message");
});
});
I fire up the server with node then load the web page in my browser (using either FF or Chrome). Using the developer tools I see that the connection appears to be made. On the server side I see the established connection using netstat. I also put an alert() in the browser side in the onopen() function and it fired.
The problem is that no console log output is produced. When connection.send(mag) is executed the on("message" event never appears to fire on the server. I'm at a loss here. I had this working as an http:// websocket server but this is my first attempt at wss:. I would appreciate any insight.
Notes:
The sever name is not example.com although that is what I show in my code.
The firewall is allowing anyone to connect on port 14000 using TCP protocol.
The cert is a working wildcard cert for the web site.

Finally figured out what it was after ignoring it for a month or so. It had to do with the symbolic link (/httpd) defined for the SSL files as in:
ssl_key: '/httpd/conf/ssl.key/my.key',
ssl_cert: '/httpd/conf/ssl.crt/my.crt',
They had to be changed to:
ssl_key: '/usr/local/apache2/conf/ssl.key/my.key',
ssl_cert: '/usr/local/apache2/conf/ssl.crt/my.crt',
Who knew that symbolic links were frowned upon? Well, now we all do.

Related

How do I define Watershed in Node.js?

When I execute the following code, I get the error: Reference Error: Watershed is not defined. How can I define it? Do I need a module to be installed for it?
var restify=require('restify');
var ws= new Watershed();
var server=restify.createServer();
server.get('websocket/attach', function upgradeRoute(req, res, next){
if(!res.claimUpgrade){
next(new Error("Connection must be upgraded."));
return;
}
var upgrade=res.claimUpgrade();
var shed=ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function (msg){
console.log("The message is: "+msg);
});
shed.send("hello there");
next(false);
});
server.listen(8081, function(){
console.log('%s listening at %s', server.name, server.url);
});
There is also a section of the restify doc that mentioned how to handle the ability to upgrade sockets. I just struggled with this for an emarrassingly long time and thought I'd share the simple solution. In addtion the #Dibu Raj reply, you also need to create your restify server with the handleUpgrades option set to true. Here is a complete example to make restify work with websocket upgrades and watershed:
'use strict';
var restify = require('restify');
var watershed = require('watershed');
var ws = new watershed.Watershed();
var server = restify.createServer({
handleUpgrades: true
});
server.get('/websocket/attach', function (req, res, next) {
if (!res.claimUpgrade) {
next(new Error('Connection Must Upgrade For WebSockets'));
return;
}
console.log("upgrade claimed");
var upgrade = res.claimUpgrade();
var shed = ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function(msg) {
console.log('Received message from websocket client: ' + msg);
});
shed.send('hello there!');
next(false);
});
//For a complete sample, here is an ability to serve up a subfolder:
server.get(/\/test\/?.*/, restify.serveStatic({
directory: './static',
default: 'index.html'
}));
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
For an html page to test your new nodejs websocket server: write this html below into a file at ./static/test/index.html - point your browser to http://localhost:8080/test/index.html - open your browser debug console to see the message exchange.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Socket test area</title>
<meta name="description" content="Web Socket tester">
<meta name="author" content="Tim">
</head>
<body>
Test Text.
<script>
(function() {
console.log("Opening connection");
var exampleSocket = new WebSocket("ws:/localhost:8080/websocket/attach");
exampleSocket.onopen = function (event) {
console.log("Opened socket!");
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
exampleSocket.onmessage = function (event) {
console.log("return:", event.data);
exampleSocket.close();
}
})();
</script>
</body>
</html>
Your browser log will look something like this:
07:05:05.357 index.html:18 Opening connection
07:05:05.480 index.html:22 Opened socket!
07:05:05.481 index.html:26 return: hello there!
And your node log will look like:
restify listening at http://[::]:8080
client connected!
Rest service called started
upgrade claimed
Received message from websocket client: Here's some text that the server is urgently awaiting!
Documentation for this found at:
http://restify.com/#upgrade-requests
You should include the watershed library
var Watershed = require('lib/watershed').Watershed;

socket.io 404 cant connect with socket.io server

I have webrtc / socket.io / nodejs running on a server, everything works fine when i go to the https://domain.com:8080 to test a video conference.
But i want the script to run in my webserver /public_html/
But i dont know why it is not connecting to the 8080 server.
"socket.io.js GET https://domain.com/socket.io/?EIO=3&transport=polling&t=LPgZs2K 404 (Not Found)"
my server (server.js)
// Load required modules
var https = require("https"); // http server core module
var express = require("express"); // web framework external module
var serveStatic = require('serve-static'); // serve static files
var socketIo = require("socket.io"); // web socket external module
var easyrtc = require("../");
const fs = require('fs'); // EasyRTC external module
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
// Set process name
process.title = "node-easyrtc";
// Setup and configure Express http server. Expect a subfolder called "static" to be the web root.
var app = express();
app.use(serveStatic('static', {'index': ['index.html']}));
// Start Express http server on port 8080
var webServer = https.createServer(options, app).listen(8080);
// Start Socket.io so it attaches itself to Express server
var socketServer = socketIo.listen(webServer, {"log level":1});
easyrtc.setOption("logLevel", "debug");
// Overriding the default easyrtcAuth listener, only so we can directly access its callback
easyrtc.events.on("easyrtcAuth", function(socket, easyrtcid, msg, socketCallback, callback) {
easyrtc.events.defaultListeners.easyrtcAuth(socket, easyrtcid, msg, socketCallback, function(err, connectionObj){
if (err || !msg.msgData || !msg.msgData.credential || !connectionObj) {
callback(err, connectionObj);
return;
}
connectionObj.setField("credential", msg.msgData.credential, {"isShared":false});
console.log("["+easyrtcid+"] Credential saved!", connectionObj.getFieldValueSync("credential"));
callback(err, connectionObj);
});
});
// To test, lets print the credential to the console for every room join!
easyrtc.events.on("roomJoin", function(connectionObj, roomName, roomParameter, callback) {
console.log("["+connectionObj.getEasyrtcid()+"] Credential retrieved!", connectionObj.getFieldValueSync("credential"));
easyrtc.events.defaultListeners.roomJoin(connectionObj, roomName, roomParameter, callback);
});
// Start EasyRTC server
var rtc = easyrtc.listen(app, socketServer, null, function(err, rtcRef) {
console.log("Initiated");
rtcRef.events.on("roomCreate", function(appObj, creatorConnectionObj, roomName, roomOptions, callback) {
console.log("roomCreate fired! Trying to create: " + roomName);
appObj.events.defaultListeners.roomCreate(appObj, creatorConnectionObj, roomName, roomOptions, callback);
});
});
//listen on port 8080
webServer.listen(8080, function () {
console.log('listening on http://localhost:8080');
});
my html file on de WEB server. structure like this https://domain.com/test.html
<!DOCTYPE html>
<html>
<head>
<title>EasyRTC Demo:EasyRTC Demo: Video+Audio HD 720</title>
<link rel="stylesheet" type="text/css" href="/easyrtc/easyrtc.css" />
<script src="js/socket.io.js"></script>
<script type="text/javascript" src="js/easyrtc.js"></script>
<script type="text/javascript" src="js/video.js"></script>
<script>
var selfEasyrtcid = "";
function connect() {
easyrtc.setVideoDims(1280,720);
easyrtc.enableDebug(false);
easyrtc.setRoomOccupantListener(convertListToButtons);
easyrtc.easyApp("easyrtc.videoChatHd", "selfVideo", ["callerVideo"], loginSuccess, loginFailure);
}
function clearConnectList() {
var otherClientDiv = document.getElementById("otherClients");
while (otherClientDiv.hasChildNodes()) {
otherClientDiv.removeChild(otherClientDiv.lastChild);
}
}
function convertListToButtons (roomName, data, isPrimary) {
clearConnectList();
var otherClientDiv = document.getElementById("otherClients");
for(var easyrtcid in data) {
var button = document.createElement("button");
button.onclick = function(easyrtcid) {
return function() {
performCall(easyrtcid);
};
}(easyrtcid);
var label = document.createTextNode(easyrtc.idToName(easyrtcid));
button.appendChild(label);
button.className = "callbutton";
otherClientDiv.appendChild(button);
}
}
function performCall(otherEasyrtcid) {
easyrtc.hangupAll();
var acceptedCB = function(accepted, caller) {
if( !accepted ) {
easyrtc.showError("CALL-REJECTED", "Sorry, your call to " + easyrtc.idToName(caller) + " was rejected");
}
};
var successCB = function() {};
var failureCB = function() {};
easyrtc.call(otherEasyrtcid, successCB, failureCB, acceptedCB);
}
function loginSuccess(easyrtcid) {
selfEasyrtcid = easyrtcid;
document.getElementById("iam").innerHTML = "I am " + easyrtc.cleanId(easyrtcid);
}
function loginFailure(errorCode, message) {
easyrtc.showError(errorCode, message);
}
// Sets calls so they are automatically accepted (this is default behaviour)
easyrtc.setAcceptChecker(function(caller, cb) {
cb(true);
} );
</script>
</head>
<body onload="connect();">
<h1>EasyRTC Demo: Video+Audio HD 720p</h1>
<div id="demoContainer">
<div>
Note: your own image will show up postage stamp sized, while the other party"s video will be shown in high-definition (1280x720). Note: not all webcams are seen by WebRTC as providing high-definition video; the fallback is to use standard definition (640x480).
</div>
<div id="connectControls">
<div id="iam">Not yet connected...</div>
<br />
<strong>Connected users:</strong>
<div id="otherClients"></div>
</div>
<div id="videos">
<div style="position:relative;float:left;" width="1282" height="722">
<video autoplay="autoplay" id="callerVideo"></video>
<video class="easyrtcMirror" autoplay="autoplay" id="selfVideo" muted="true" volume="0" ></video>
</div>
<!-- each caller video needs to be in it"s own div so it"s close button can be positioned correctly -->
</div>
</div>
</body>
</html>
Socket.io.js: http://81.171.38.245/js/socket.io.js

Not able to connect to Mosquitto Server from mqtt.js

I am new to wqtt server. I am trying to connect to mosquitto test server using mqtt.js reffering an example provided on their website.
But i am not able to connect to the server. I always get following error:
WebSocket connection to 'ws://test.mosquitto.org/:8080/mqtt' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED.
Please help. Below is my html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="http://www.hivemq.com/demos/websocket-client/js/mqttws31.js" type="text/javascript"></script>
<title>HiveMQ MQTT Websocket Demo App</title>
<script type="text/javascript">
var client = new Messaging.Client("test.mosquitto.org", 8080, "myclientid_" + parseInt(Math.random() * 100, 10));
//Gets called if the websocket/mqtt connection gets disconnected for any reason
client.onConnectionLost = function (responseObject) {
//Depending on your scenario you could implement a reconnect logic here
alert("connection lost: " + responseObject.errorMessage);
};
//Gets called whenever you receive a message for your subscriptions
client.onMessageArrived = function (message) {
//Do something with the push message you received
$('#messages').append('Topic: ' + message.destinationName + ' | ' + message.payloadString + '');
};
//Connect Options
var options = {
timeout: 3,
//Gets Called if the connection has sucessfully been established
onSuccess: function () {
alert("Connected");
},
//Gets Called if the connection could not be established
onFailure: function (message) {
document.write("Connection failed: " + message.errorMessage);
alert("Connection failed: " + message.errorMessage);
}
};
//Creates a new Messaging.Message Object and sends it to the HiveMQ MQTT Broker
var publish = function (payload, topic, qos) {
//Send your message (also possible to serialize it as JSON or protobuf or just use a string, no limitations)
var message = new Messaging.Message(payload);
message.destinationName = topic;
message.qos = qos;
client.send(message);
}
</script>
</head>
<body>
<button onclick="client.connect(options);">1. Connect</button>
<button onclick="client.subscribe('testtopic/#', {qos: 2}); alert('Subscribed');">2. Subscribe</button>
<button onclick="publish('Hello Foo !','testtopic/bar',2);">3. Publish</button>
<button onclick="client.disconnect();">(4. Disconnect)</button>
<div id="messages"></div>
</body>
From your error message I can see 2 issues.
test.mosquitto.org listens for Websocket connections on 8080 not 1883
There should be no http:// in the url to connect to a websocket server
Also the error message does not match the details you have included in the code sample.

Connection closed before receiving a handshake response

i write a node program,and i encounter a big difficult.
the server side code is below:
var express=require("express");
var app=express();
var socketio=require("socket.io");
var server=require("http").Server(app);
var ws=socketio.listen(server);
app.use(express.static('public'));
app.listen(3000);
ws.on('connection',function(socket){
socket.on("message",function(msg){
console.log("got:"+msg);
socket.send('pong');
});
});
the client side code is below:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>websocket echo</title>
</head>
<body>
<h1>websocket echo</h1>
<h2>latency:<span id="latency"></span>ms</h2>
<script>
var lastMessage;
window.onload=function(){
//create socket
var ws=new WebSocket("ws://127.0.0.1:3000");
ws.onopen=function(){
//send first ping
ping();
};
// 监听Socket的关闭
ws.onclose = function(event) {
console.log('Client notified socket has closed',event);
};
ws.onmessage=function(ev){
console.log("got:"+ev.data);
document.getElementById("latency").innerHTML=new Date-lastMessage;
ping();
};
function ping(){
lastMessage= + new Date;
ws.send("ping");
}
}
</script>
</body>
</html>
there is the tip in chrome console:
WebSocket connection to 'ws://127.0.0.1:3000/' failed: Connection closed before receiving a handshake response (index):16
Client notified socket has closed CloseEvent
As mentioned in the comments this happens because socket.io should be connected with it's own client. You should either use websockets or socket.io on both sides.

how to send messages using socket.io

I want to use socket.io and node as a layer for my "push notification feature", so I'm running both apache and node.
I have the following code on my server (node)
var app = require('http').createServer(handler)
, io = require('C:/path/to/file/socket.io').listen(app)
, fs = require('fs');
app.listen(8080);
function handler(req, res) {
console.log(req);
fs.readFile('C:/path/to/file/index.html',
function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.on('my event', function (msg) {
console.log("DATA!!!");
});
});
the page is then served by apache from localhost without 8080 port
and on the client I have the following code:
var socket = io.connect('http://localhost:8080');
and when a button is clicked:
socket.emit('my event', {data:"some data"});
I see nothing on the node console ... why is that? cross domain issue?
Update:
it works just fine on safari 5.1.5 and even IE 9, but not on chrome(18.0.1025.151) or firefox (11.0) ... what am I missing?
here is the node log:
info - socket.io started
debug - served static content /socket.io.js
debug - client authorized
info - handshake authorized 4944162402088095824
debug - setting request GET /socket.io/1/websocket/4944162402088095824
debug - set heartbeat interval for client 4944162402088095824
debug - client authorized for
debug - websocket writing 1::
debug - setting request GET /socket.io/1/xhr-polling/4944162402088095824?t=13
33977095905
debug - setting poll timeout
debug - discarding transport
debug - cleared heartbeat interval for client 4944162402088095824
That should work fine, just make sure that in your index.html you have :
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
also, since you're serving your page via Apache, you really don't need the handler and the http server in you node file.
this should work just fine :
var io = require('socket.io').listen(8080);
io.sockets.on('connection', function (socket) {
socket.on('my event', function (msg) {
console.log("DATA!!!");
});
});
and for the index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World!</title>
<meta charset="utf-8">
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var socket = io.connect('http://localhost:8080');
$("#button").click(function() {
socket.emit('my event' ,"Hello World!");
})
})
</script>
</head>
<body>
<button type="button" id='button'>Send Message</button>
</body>
</html>
Edit: This works in both Firefox and Chrome.

Categories

Resources