nodejs does not emit data to client - javascript

I have simple nodejs app with sockets and I've faced an error where I can't find any solution. So I'm emiting from app to client and nothing happens there. Or client can't receive it - I don't know, because I can't check if it was successfully emited to client. This is the error I got when I tried to debug callback of emit:
Error: Callbacks are not supported when broadcasting
This my app code:
http.listen(6060, function () {
console.log("Listening on *: 6060");
});
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('***' == domain) {
accept(null, true);
} else {
return accept('You must be logged in to take an action in this site!', false);
}
});
io.use(function (sock, next) {
var handshakeData = sock.request;
var userToken = handshakeData._query.key;
if (typeof userToken !== null && userToken !== 0 && userToken !== '0' && userToken.length > 0) {
connection.query('***',
[xssfilter.filter(validator.escape(userToken))],
function (error, data) {
if (error) {
debug('Cant receive user data from database by token');
next(new Error('Failed to parse user data! Please login!'));
} else {
// load data to this user.
_updateUsers(xssfilter.filter(validator.escape(userToken)), 'add', data[0], sock.id);
_loadPreData();
next(null, true);
}
});
} else {
debug('Cant receive user token');
next(new Error('Failed to parse user data! Please login!'));
}
sock.on("disconnect", function () {
_updateUsers(false, 'remove', false, sock.id);
});
});
// we need to show people online count
io.emit('online-count', {
count: Object.keys(connectedUsers).length
});
And the function used above:
function _updateUsers(userToken, action, userData, sockedID) {
switch (action) {
case 'add':
connectedUsers[sockedID] = {...};
io.emit('online-count', io.emit('online-count', {
count: Object.keys(connectedUsers).length
}););
break;
case 'remove':
delete connectedUsers[sockedID];
io.emit('online-count', io.emit('online-count', {
count: Object.keys(connectedUsers).length
}););
break;
}
}
so after emiting online-count I should accept it on the client side as I'm doing it:
var socket;
socket = io(globalData.socketConn, {query: "key=" + globalData.userData.token});
socket.on('connect', function (data) {
console.log('Client side successfully connected with APP.');
});
socket.on('error', function (err) {
error('danger', 'top', err);
});
socket.on('online-count', function (data) {
console.log('Got online count: ' + data.count);
$('#online_count').html(data.count);
});
but the problem is with this online-count.. Nothing happens and it seems that it's not was even sent from node app. Any suggestions?

The problem was with my logic - I was sending online count only if new user were connecting/disconnecting. Problem were solved by adding function to repeat itself every few seconds and send online count to client side.

Related

How do I disconnect clients from the session with opentok?

Anytime I call the session.disconnect() method to remove clients from the session, I get this warning: "OpenTok:Publisher:warn Received connectivity event: "Cancel" without "Attempt"
and this error: "OpenTok:Subscriber:error Invalid state transition: Event 'disconnect' not possible in state 'disconnected'"
Could someone please explain to me what that error means? Thanks in advance.
// Initialize the session
var session = OT.initSession(data['apikey'], data['session_id']);
console.log(session);
// Initialize the publisher for the recipient
var publisherProperties = {insertMode: "append", width: '100%', height: '100%'};
var publisher = OT.initPublisher('publisher', publisherProperties, function (error) {
if (error) {
console.log(`Couldn't initialize the publisher: ${error}`);
} else {
console.log("Receiver publisher initialized.");
}
});
$('#session-modal').modal("show");
// Detect when new streams are created and subscribe to them.
session.on("streamCreated", function (event) {
console.log("New stream in the session");
var subscriberProperties = {insertMode: 'append', width: '100%', height: '100%'};
var subscriber = session.subscribe(event.stream, 'subscriber', subscriberProperties, function(error) {
if (error) {
console.log(`Couldn't subscribe to the stream: ${error}`);
} else {
console.log("Receiver subscribed to the sender's stream");
}
});
});
//When a stream you publish leaves a session, the Publisher object dispatches a streamDestroyed event:
publisher.on("streamDestroyed", function (event) {
console.log("The publisher stopped streaming. Reason: "
+ event.reason);
});
//When a stream, other than your own, leaves a session, the Session object dispatches a streamDestroyed event:
session.on("streamDestroyed", function (event) {
console.log("Stream stopped. Reason: " + event.reason);
session.disconnect();
console.log("called session.disconnect().");
});
session.on({
connectionCreated: function (event) {
connectionCount++;
if (event.connection.connectionId != session.connection.connectionId) {
console.log(`Another client connected. ${connectionCount} total.`);
}
},
connectionDestroyed: function connectionDestroyedHandler(event) {
connectionCount--;
console.log(`A client disconnected. ${connectionCount} total.`);
}
});
// Connect to the session
// If the connection is successful, publish an audio-video stream.
session.connect(data['token'], function(error) {
if (error) {
console.log("Error connecting to the session:", error.name, error.message);
} else {
console.log("Connected to the session.");
session.publish(publisher, function(error) {
if (error) {
console.log(`couldn't publish to the session: ${error}`);
} else {
console.log("The receiver is publishing a stream");
}
});
}
});
// Stop the publisher from streaming to the session if the user dismiss the modal
const stopSession = document.getElementById('stop-session');
stopSession.addEventListener("click", (event) => {
event.preventDefault();
session.disconnect();
});
I see this is kind of old, but wanted to share my solution to avoid this error. I'm not sure what the error means, but I call publisher.destroy() before calling session.disconnect() to avoid the error.
openTokPublisher.destroy();
openTokSession.disconnect();
I highly doubt you can disconnect the client with JavaScript. Here what I did.
// Connect to the session
session.connect(token, function connectCallback(error) {
// Get the connectionId
connectionId = session.connection.connectionId;
and use one of their SDK on the backend
https://tokbox.com/developer/sdks/server/
// Disconnect session
function disconnectSession() { // eslint-disable-line no-unused-vars
if (sessionId && connectionId) {
$.ajax({
url: '/OpenTok/DisconnectSession',
type: 'POST',
data: 'sessionId=' + sessionId + '&connectionId=' + connectionId,
});
}
}

Azure + Node Js Service bus persistent subscription of topic

Using node js i want to create persistent subscription for Azure service bus service topic. right now it is execute only once. Please guide me I am new to this. Thanks in advance. I am using following code to subscribe topic.
var azure = require('azure');
var azureConnection = "Endpoint=sb:My connection string"
var retryOperations = new azure.ExponentialRetryPolicyFilter();
var serviceBusService = azure.createServiceBusService(azureConnection).withFilter(retryOperations);
serviceBusService.receiveSubscriptionMessage('mytopic01', 'mytopicsub', function (error, receivedMessage) {
if (!error) {
// // // Message received and deleted
console.log(receivedMessage);
}
});
Also I don't want to use setInterval function. I want to solution if message publish to the topic it should automatically trigger subscription.
Actually, if your client application is an independent node.js application, we usually set up a cycle program to receive message from service bus in loop.
E.G.
var azure = require('azure');
var sbService = azure.createServiceBusService(<connection_string>);
function checkForMessages(sbService, queueName, callback) {
sbService.receiveSubscriptionMessage(queueName, { isPeekLock: true }, function (err, lockedMessage) {
if (err) {
if (err === 'No messages to receive') {
console.log('No messages');
} else {
callback(err);
}
} else {
callback(null, lockedMessage);
}
});
}
function processMessage(sbService, err, lockedMsg) {
if (err) {
console.log('Error on Rx: ', err);
} else {
console.log('Rx: ', lockedMsg);
sbService.deleteMessage(lockedMsg, function(err2) {
if (err2) {
console.log('Failed to delete message: ', err2);
} else {
console.log('Deleted message.');
}
})
}
}
setInterval(checkForMessages.bind(null, sbService, queueName, processMessage.bind(null, sbService)), 5000);
You can refer to the code sample in the similar scenario at GitHub provided by Azure Team.
Any further concern, please feel free to let me know.

Get return value when using call() with node.js

I am currently programming a socket server in node.js using the json-socket module, and am having some trouble.
Currently when a client connects to the server they send a command in a json object with some data for instance a login would look like this
{ type : 'login', data : { username: 'Spero78' } }
to deal with these requests i have a commands object
var commands = {
'login' : authUser,
'register' : userRegister
}
and these functions are called by server.on
server.on('connection', function(socket) {
console.log('Client Connected');
socket = new JsonSocket(socket);
socket.on('message', function(message) {
if(message.type != undefined) {
if(commands[message.type]){
var response = commands[message.type].call(this, message.data);
if(response != undefined){
console.log(response);
socket.sendMessage(response);
} else {
console.log("No Response!");
}
} else {
console.log('Unexpected Command!');
}
}
});
});
The functions return javascript objects but the response var is always undefined and the "No Response!" message is always printed
Here is the authUser function
function authUser(data){
console.log('Auth: ' + data.username);
database.query('SELECT * FROM players WHERE username = ?', [data.username], function(err, results) {
if(results.length < 1){
console.log('Bad Login!');
var response = {
type : 'badlogin',
data : {
//...
}
}
return response;
}
var player = results[0];
var response = {
type : 'player',
data : {
//...
}
}
return response;
});
}
Is there a better way of doing this? or am i missing something that is causing the objects to not return
database.query() is asynchronous, so when you call this function, nodejs don't wait the response of the callback to go to next instruction.
So the value tested on your condition is not the return in the callback, but of the whole authUser function, that's why it's always undefined.
You probably need tor refactor your code.

Redis connection close

Im using connect-domain and connect-redis. Below code checks for redis cache in Redis database.
function redis_get(key, req, res) {
var redisClient = redis.createClient();
redisClient.get(redisKey, function (err, data) {
if (err) {
console.log("Error in RedisDB");
}
else if (data == null) {
// Calling external function
}
else {
// Calling external function
}
redisClient.quit(); // Not working
});
}
When cache is not avaiable Im calling external function. I want redis connection to be closed once the cache check has been done.
redisClient.quit() // Not working
Any help on this will be really helpful.
Thanks
Below code is working fine without any problem.So check your status reply in the quit method if you get status as 'OK' means that method is working fine.
var redis=require('redis');
var redisClient = redis.createClient();
redisClient.get('name', function (err, data) {
if (err) {
console.log("Error in RedisDB");
}
else if (data == null) {
console.log('null');
}
else {
console.log(data);
}
redisClient.quit(redis.print);
});

Socket.io.js - connection still established after rejecting it while authorization

I was using express v3.0.0, sockek.io, and redis. Something weird happened when a user without authorization request a connection. The line console.log( 'Error!!!'); was run and the connection should be rejected by the next line return accept(err, false);. However, the connection was still established, and the line socket.log.info('A socket with sessionID', hs.sessionID, 'connected'); was run.
io = socketIO.listen(server);
io.configure(function () {
io.set('authorization', function (data, accept) {
// check if there's a cookie header
if (data.headers.cookie) {
data.cookie = parseSignedCookies(cookie.parse(decodeURIComponent(data.headers.cookie)), 'secret');
data.sessionID = data.cookie['connect.sid'];
// save the session store to the data object
// (as required by the Session constructor)
data.sessionStore = sessionStore;
sessionStore.get(data.sessionID, function (err, session) {
if (session) {
req = {
sessionStore: sessionStore
, sessionID: data.sessionID
};
session = new express.session.Session(req, session);
}
if (err || !session) {
console.log( 'Error!!!');
return accept(err, false);
} else {
// create a session object, passing data as request and our
// just acquired session data
data.session = new Session(data, session);
return accept(null, true);
}
});
} else {
// if there isn't, turn down the connection with a message
// and leave the function.
return accept('No cookie transmitted', false);
}
// accept the incoming connection
accept(null, true);
});
});
io.sockets.on('connection', function (socket) {
var hs = socket.handshake;
socket.log.info('A socket with sessionID', hs.sessionID, 'connected');
// setup an inteval that will keep our session fresh
var intervalID = setInterval(function () {
// reload the session (just in case something changed,
// we don't want to override anything, but the age)
// reloading will also ensure we keep an up2date copy
// of the session with our connection.
hs.session.reload( function () {
// "touch" it (resetting maxAge and lastAccess)
// and save it back again.
hs.session.touch().save();
});
}, 60 * 1000);
socket.on('disconnect', function () {
socket.log.info('A socket with sessionID', hs.sessionID, 'disconnected');
// clear the socket interval to stop refreshing the session
clearInterval(intervalID);
});
});
The problem is in the last line of your authorization method:
// accept the incoming connection
accept(null, true);
because
sessionStore.get(data.sessionID, function (err, session) {
works asynchronous. You MUST NOT return any values from within the authorization function directly but only from the sessionStore.get callback function.
The complete code should be:
io = socketIO.listen(server);
io.configure(function () {
io.set('authorization', function (data, accept) {
// check if there's a cookie header
if (data.headers.cookie) {
data.cookie = parseSignedCookies(cookie.parse(decodeURIComponent(data.headers.cookie)), 'secret');
data.sessionID = data.cookie['connect.sid'];
// save the session store to the data object
// (as required by the Session constructor)
data.sessionStore = sessionStore;
sessionStore.get(data.sessionID, function (err, session) {
if (session) {
req = {
sessionStore: sessionStore
, sessionID: data.sessionID
};
session = new express.session.Session(req, session);
}
if (err || !session) {
console.log( 'Error!!!');
return accept(err, false);
} else {
// create a session object, passing data as request and our
// just acquired session data
data.session = new Session(data, session);
return accept(null, true);
}
});
}
});
});
Per the latest versions of Socke.io, the io.set('authorization') is deprecated.
Instead, use Middlewares.
A code snippet from my project is as follows:
io.use(SocketAuthRules.ensureUser)
In SocketAuthRules module, I have a function
function ensureUser (socket, next){
if(user!==null) {
next()
}
else {
next(new Error('not authorized'));
}
}

Categories