Why i cannot send messages with pidgin to node xmpp server? - javascript

I have implemented a nodejs xmpp server. As a client i have pidgin. I can't send messages from pidgin to server. Why? I can connect and authentication works.
This is my server code:
'use strict'
var xmpp = require('../index')
, server = null
, Client = require('node-xmpp-client')
var startServer = function(done) {
// Sets up the server.
server = new xmpp.C2S.TCPServer({
port: 5222,
domain: 'localhost'
})
// On connection event. When a client connects.
server.on('connection', function(client) {
// That's the way you add mods to a given server.
// Allows the developer to register the jid against anything they want
client.on('register', function(opts, cb) {
console.log('REGISTER')
cb({code: 'foo', type: 'bar'})
})
// Allows the developer to authenticate users against anything they want.
client.on('authenticate', function(opts, cb) {
console.log('server:', opts.username, opts.password, 'AUTHENTICATING')
if (opts.password === 'secret') {
console.log('server:', opts.username, 'AUTH OK')
cb(null, opts)
}
else {
console.log('server:', opts.username, 'AUTH FAIL')
cb(false)
}
})
client.on('online', function() {
console.log('server:', client.jid.local, 'ONLINE')
client.send(new xmpp.Element('iq', { type: 'chat', 'xml:lang': 'ko' }).c('body').t('Welcome to server!'))
})
// Stanza handling
client.on('stanza', function(stanza) {
console.log('server:', client.jid.local, 'stanza', stanza.toString())
//var from = stanza.attrs.from
//stanza.attrs.from = stanza.attrs.to
//stanza.attrs.to = from
console.log(stanza.toString());
client.send(stanza.toString())
//console.log('Stanza sent is :'+stanza);
})
// On Disconnect event. When a client disconnects
client.on('disconnect', function() {
console.log('server:', client.jid.local, 'DISCONNECT')
})
})
server.on('listening', done)
}
startServer(function() {
})

Related

NodeJS Unable to connect to Websocket Cross origin - "Err 1006"

I have a two webservers both running https with the same certificates, I have a main shard that the user connects to example.com, they retrieve some data and try to connect to an ip address on the 2nd shard via websocket.
But no matter what I configure I get an Error 1006 on the client side when connecting to the 2nd shard. Firefox devtooling gives me multiple errors - ssl_error_bad_cert_domain, SSL_ERROR_RX_RECORD_TOO_LONG.
The certificates are issued and signed, I was wondering where I should go from here. Thanks :)
SHARD2
const options = {
key: './server.key',
cert: './server.cert'
};
var https = require('https').Server(options);
https.listen(443, function () {
// console.log('Https listening on *: 443');
});
let WebSocket = require('ws');
let socket = new WebSocket.Server({ server:https });
socket.on('connection', function (ws, req) {
ws.on('message', (msgRaw) =>{
});
ws.on('close', function(code, reason) {
});
ws.on('error', function(error) {
console.log(error);
ws.close();
});
});
CLIENT
function connect() {
"use strict";
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
alert('Your browser doesn\'t support WebSocket');
return;
}
wss = new WebSocket('wss://123.123.123.120/:443');
wss.onmessage = function(event) {
};
wss.onerror = function(event) {
console.log(`wss error: ${JSON.stringify(event)}`);
};
wss.onclose = function(event) {
};
}
Useful sys diagram?

Firefox can’t establish a connection to the server at wss://localhost:8000/

I am using nodejs to run the server, there is no log file
This is my server.js
const https = require('https');
const fs = require('fs');
const ws = require('ws');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const wss = new ws.Server({noServer: true});
function accept(req, res) {
// all incoming requests must be websockets
if (!req.headers.upgrade || req.headers.upgrade.toLowerCase() != 'websocket') {
res.end();
return;
}
// can be Connection: keep-alive, Upgrade
if (!req.headers.connection.match(/\bupgrade\b/i)) {
res.end();
return;
}
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onConnect);
}
function onConnect(ws) {
ws.on('message', function (message) {
let name = message.match(/([\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]+)$/gu) || "Guest";
ws.send(`${name}!`);
//setTimeout(() => ws.close(1000, "Bye!"), 5000);
});
}
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
This is my code in react
componentDidMount() {
var connection = new WebSocket('wss://localhost:8000/');
connection.onopen = function(e) {
connection.send("add people");
};
connection.onmessage = function(event) {
// alert(`[message] Data received from server: ${event.data}`);
console.log("output ", event.data);
};
}
While I am trying to connect with web-socket with my jsx file its give me an error which is Firefox can’t establish a connection to the server at wss://localhost:8000/.
Your implementaion needs some changes. In the backend server, you forgot to call the onConnect function. So your ws.on method will never call.
Also, you imported the ws and create a WebSocket server wss, but you add some event listener on ws wrongly, you should add listener on your Websocket instance (wss):
// rest of the codes ...
const was = new ws.Server({noServer: true})
wss.on('connection`) {
// do something here ...
}
// rest of the codes ...
https.createServer(options, () => {
// do something here ...
})
There are some examples of how to create the WebSocket server along with the HTTP server on ws npm page.

identifying users upon some action or disconnected

I'm new to node
I have a PHP/Laravel cms and I have a simple Nodejs game server which is basically a loop generating some numbers
I connect my PHP backend to Nodejs via Socketio and use Socketio-JWT to identify the user
my client side (php/laravel)
PHP
$userToken = JWTAuth::customClaims(['userid' => Auth::user()->id, 'name' => Auth::user()->name, 'avatar' => asset_url('image/avatar-default.png')])->fromUser(Auth::user() );
html/js
var socket = io.connect("http://localhost:666");
socket.on('connect', function () {
socket.emit('authenticate', {token: '{{$userToken}}'});
});
socket.on('authenticated', function () {
console.log('Authenticated');
});
socket.on('unauthorized', function (data) {
console.log('Unauthorized, error msg: ' + data.message);
});
my serverside
const _online_users = { };
io.sockets
.on('connection', socketioJwt.authorize({
secret: JWT_SECRET,
timeout: 15000
}))
.on('authenticated', function(socket) {
_online_users[socket.decoded_token.userid] = {
name : socket.decoded_token.name ,
avatar : socket.decoded_token.avatar ,
}
io.sockets.emit('update_online_users' , _online_users );
socket.on('disconnect', function() {
console.log(`----- ##disconnect -----`)
});
}) ;
as you can see I have an object called _online_users and I store authenticated users in this object and then I send it to the clients so they know who is online
io.sockets.emit('update_online_users' , _online_users );
here is the problem, when the user gets disconnected
socket.on('disconnect', function() {
console.log(`----- ##disconnect -----`)
});
I have to update my _online_users object and remove disconnected user .... how should I go about this? I was thinking maybe I can store the token itself in the _online_users
_online_users[socket.decoded_token.userid] = {
token : socket.token ,
name : socket.decoded_token.name ,
avatar : socket.decoded_token.avatar ,
}
and when the user gets disconnected I get the disconnected token from the socket and remove the user from an object by that token
of course, this is all theory! I'm not sure if that's the way to go .... first of all, I can't access the token itself from the socket !
or let's say one of the users sends another request to node server, how can I identify the user sending the request?
.on('authenticated', function(socket) {
socket.on('somaction', function() {
console.log(` who is this guy ? `)
});
})
is there anything unique insocket.decoded_token that I can use as id? if so I can store it in the online users send it back and forth when the user requests something
basically I'm lost and appreciate any pointers
You can use a middleware now in the newer versions of socket-io. So you can check if the user is logged in by the jwt token that is sent with the request. If decoded successfully you can assign the user info to the current socket and call next() and go to the event you are listening for. Here is the example provided in the socket-io docs slightly modified for your case.
io.use(function(socket, next) {
const handshakeData = socket.request;
// make sure the handshake data looks good as before
// if error do this:
// next(new Error('not authorized'));
// else decode jwt token here and append the user to the socket.request
// and call next
// pseudo code here
const {
authorization
} = handshakeData.header
let token;
if (authorization && authorization.split(" ")[0] === "Bearer") {
token = authorization.split(" ")[1]
}
let user = jwt.decode(token, secret);
socket.request.user = user;
next();
});
You are doing well!
Since you are adding socket event handlers in the 'authenticated' handler you still have access to socket.decoded_token.userid.
This should be enough:
const _online_users = {};
io.sockets
.on('connection', socketioJwt.authorize({
secret: JWT_SECRET,
timeout: 15000
}))
.on('authenticated', function(socket) {
_online_users[socket.decoded_token.userid] = {
name: socket.decoded_token.name,
avatar: socket.decoded_token.avatar,
};
io.sockets.emit('update_online_users', _online_users);
socket.on('disconnect', function() {
console.log(`----- ##disconnect -----`);
delete _online_users[socket.decoded_token.userid];
io.sockets.emit('update_online_users', _online_users);
});
});
or to be a little more concise:
const _online_users = {};
io.sockets
.on('connection', socketioJwt.authorize({
secret: JWT_SECRET,
timeout: 15000
}))
.on('authenticated', function(socket) {
const { avatar, name, userid } = socket.decoded_token;
_online_users[userid] = { name, avatar };
io.sockets.emit('update_online_users', _online_users);
socket.on('disconnect', function() {
delete _online_users[userid];
io.sockets.emit('update_online_users', _online_users);
});
socket.on('any other event...', function() {
// ... still have access to userid
});
});
Edit: About unauthenticated socket I don't know; doc says nothing. You could try something like:
io.socket.on('connection', socket => {
socket.emit('update_online_users', _online_users);
// I'm afraid this closes the socket if unauthorized, you could check by yourself
socketioJwt.authorize({
secret: JWT_SECRET,
timeout: 15000
})(socket);
}).on('authenticated', socket => {
//...
});
Hope this helps.

socket.io - Client connects to two sockets by same server

I am trying to build socket connections between React client-side and Node.js server-side. But the server will host two sockets. Here is the server-side code
var app = express();
var server = http.createServer(app);
var io = require('socket.io')(2893, {
path: "/ws",
resource: "/ws",
transports: ['websocket'],
pingTimeout: 5000
});
var redis = require('redis');
const subscriber = redis.createClient();
require('./server/route')(app, io);
require('./server/lib/subscriber')(require('socket.io').listen(server), subscriber);
The first socket connection is ok, but I wonder why the second one is not working (which is attached with listen(server). Here is subscriber module I wrote:
module.exports = (io, subscriber) => {
io.sockets.on('connection', (socket) => {
console.log(socket);
socket.on('room', (room) => {
socket.join(room);
});
});
subscriber.on('pmessage', (pattern, channel, message) => {
const msg = JSON.parse(message);
const idCallcenter = msg.idCallcenter;
return io.to(idCallcenter).emit('message', { type: channel, message: msg });
});
subscriber.psubscribe('*');
};
And the client-side React module
var socketOption = { path: "/ws", transports: ['websocket'] };
var socket = io("http://localhost:2893", socketOption);
var socket2 = io.connect("http://localhost:4004");
export default function (user) {
debugger
socket.user = user;
contact(socket);
notify(socket);
socket.on('connect', function () {
debug('socket connect', socket.id);
store.dispatch(connectNetworkSuccess());
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
});
socket2.on('connect', () => {
debug('Socket connected');
socket2.emit('room', user.idCallcenter);
});
socket2.on('message', (data) => {
debugger
debug('Socket message');
debug(data);
const type = data.type;
const message = data.message;
if (type === 'recordFetched') {
}
});
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
socket.on('disconnect', function (reason) {
debug('socket disconnect', reason);
store.dispatch(connectNetworkFailed());
});
}
The first socket (in port 2893) runs normally. Meanwhile, socket2 (in port 4004) does not connect. It does not jump into connection callback of both server and client sides. What did I do wrong here?
I solved the case myself. The working code on client side is:
export default function (user) {
debugger
var socketOption = { path: "/ws", transports: ['websocket'] };
var socket = env === "local" ? io("http://localhost:2893", socketOption) : io(window.location.origin, socketOption);
var socket2 = io.connect();
socket.user = user;
contact(socket);
notify(socket);
socket.on('connect', function () {
debug('socket connect', socket.id);
store.dispatch(connectNetworkSuccess());
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
});
socket2.on('connect', () => {
console.log('Socket connected');
socket2.emit('room', user.idCallcenter);
});
socket2.on('message', (data) => {
debugger
console.log('Socket message', data);
const type = data.type;
const message = data.message;
if (type === 'recordFetched') {
}
});
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
socket.on('disconnect', function (reason) {
debug('socket disconnect', reason);
store.dispatch(connectNetworkFailed());
});
}
The server did jump into connection callback, but not room callback. I suppose it is because the connect callback of client side was defined after the connection is made, so that it couldn't jump into it. This is my possibility. Am I right?

Nodejs only specific logged users can get message

when users online and don't close our clients such as browser tab or android application, i can send message to each specific user by
socket.broadcast.to(socketId)
.emit('new message', {
username: data.fromUsername,
money : 'Hurrraaa'
});
when users close clients as mobile application this event don't trigger but i can send any message to broadcast as:
socket.broadcast.emit('new message', "hooooorrrrraaaaa");
my users don't use client application any time, but i need to send message to some specific user and notify user until opening application and see message, users should be on'time in my application to get every message which i want to send from server like with Chat messengers which don't need users currently are using application such as WhatsApp, how can i resolve this problem?
then problem is send message to some specific users when they are istalled application and logged ti sever, but not using now and application waiting to receive message such as broadcast or special message to himself
this code is my simplified server:
var socket = require('socket.io'),
express = require('express'),
app = express(),
server = require('http').createServer(app),
io = socket.listen(server),
port = process.env.PORT || 3000,
mysql = require('mysql'),
uuid = require('node-uuid'),
datetime = require('node-datetime'),
moment = require('moment'),
bcrypt = require('bcrypt'),
async = require('async'),
request = require('request'),
redis = require("redis"),
redisClient = redis.createClient(),
forever = require('forever'),
log = require('log4node');
var io_redis = require('socket.io-redis');
io.adapter(io_redis({host: 'localhost', port: 6379}));
require('sticky-socket-cluster/replace-console')();
var options = {
workers : require('os').cpus().length,
first_port : 8000,
proxy_port : 3000,
session_hash: function (req, res) {
return req.connection.remoteAddress;
},
no_sockets: false
};
require('sticky-socket-cluster')(options, start);
function start(port) {
io.sockets.on('connection', function (socket) {
socket.on('new message', function (data) {
socket.broadcast.emit('new message', "hooooorrrrraaaaa");
});
socket.on('login', function (data) {
log.info(JSON.stringify(data))
login(data.username, data.password, function (success, value) {
if (success) {
redisClient.exists(data.username, function (err, doesExist) {
if (err) return;
if (!doesExist) {
redisClient.set(data.username, socket.id, function (err, res) {
redisClient.set(data.username, socket.id);
});
}
else {
redisClient.del(data.username);
redisClient.set(data.username, socket.id, function (err, res) {
redisClient.set(data.username, socket.id);
});
}
});
socket.emit('login', {
result : true,
id : value.id,
registeredMobileNumber: value.registeredMobileNumber
});
} else {
socket.emit('login', {result: false});
}
});
});
socket.on('userConnected', function (username) {
redisClient.exists(username, function (err, doesExist) {
if (err) return;
if (!doesExist) {
redisClient.set(username, socket.id, function (err, res) {
redisClient.set(username, socket.id);
});
}
else {
redisClient.del(username);
redisClient.set(username, socket.id, function (err, res) {
redisClient.set(username, socket.id);
});
}
});
});
socket.on('disconnectUser', function (data) {
redisClient.exists(data.username, function (err, doesExist) {
if (err) return;
if (doesExist) {
redisClient.del(data.username);
}
});
});
server.listen(port, function () {
console.log('Express and socket.io listening on port ' + port);
});
}
You can use socket.on('disconnect', function() {});
When a User disconnects , save the users user_id.
Subsequent message on the user_id would be saved in the server.
When the client reconnects again get the time of the latest message and then push the message after that time (saved in the server) to the client.

Categories

Resources