.on is not a function - node.js

From electron I pass node.js modules with the contextBridge to the interface like this:
const udp = require('dgram');
contextBridge.exposeInMainWorld(
'electron',
{
udp: udp,
}
)
Then for example in the web console I can do:
var udp = window.electron.udp
var client = udp.createSocket('udp4');
Most of the methods on client work.
But when I try to attach event handlers I this error:
client.on('message',function(msg,info){
console.log('Data received from server : ' + msg.toString());
});
=> VM542:1 Uncaught TypeError: client.on is not a function
I don't understand why in the web console I can't use the on-methods?
How should I listen to events there? Or could this error be related to Jquery?
Thank you
I know that I could set: contextIsolation: false but then I got other errors.
client => {_events: {…}, _eventsCount: 0, _maxListeners: undefined, type: "udp4", Symbol(kCapture): false, …}

Related

The NodeJS socket.io server is not responding

You can see for yourself that the request hangs:
curl "http://europasprak.com:9001/socket.io/?EIO=4&transport=polling"
It also hangs when sending the request from the server machine itself:
curl "http://localhost:9001/socket.io/?EIO=4&transport=polling"
I'm trying to create a socket.io server following the documentation.
I have the NodeJS socket server:
var http = require('http');
var socketio = require('socket.io');
var httpServer = http.createServer(utils.httpHandler);
httpServer.listen(config.socketio.port, function() {
console.log('The NodeJS HTTP server [port: ' + config.socketio.port + '] is listening...');
});
Using the DEBUG variable to start the server as in:
DEBUG=socket* node /usr/local/learnintouch/engine/api/js/socket/elearning-server.js 2>&1 >> /usr/local/learnintouch/logs/nodejs.log
shows:
socket.io:server creating engine.io instance with opts {"cors":{"origin":"*"},"path":"/socket.io"} +2ms
socket.io:server attaching client serving req handler +5ms
socket.io:server initializing namespace / +1ms
socket.io:server initializing namespace /elearning +10ms
The NodeJS log shows:
The NodeJS HTTP server [port: 9001] is listening...
The server object is:
{
io: Server {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_nsps: Map { '/' => [Namespace] },
parentNsps: Map {},
_path: '/socket.io',
clientPathRegex: /^\/socket\.io\/socket\.io(\.min|\.msgpack\.min)?\.js(\.map)?$/,
_connectTimeout: 45000,
_serveClient: true,
_parser: {
protocol: 5,
PacketType: [Object],
Encoder: [Function: Encoder],
Decoder: [Function: Decoder]
},
encoder: Encoder {},
_adapter: [Function],
sockets: Namespace {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
sockets: Map {},
_fns: [Array],
_ids: 0,
server: [Circular],
name: '/',
adapter: [RedisAdapter],
[Symbol(kCapture)]: false
},
opts: { cors: [Object] },
[Symbol(kCapture)]: false
}
}
The connection is then handled like this:
module.exports.io = socketio(httpsServer, {
cors: {
origin: '*',
}
});
module.exports.io.adapter(ioredis({ host: config.redis.hostname, port: config.redis.port }));
var redisClient = redis.createClient(config.redis.port, config.redis.hostname);
module.exports.io.use(function (socket, handler) {
console.log('The namespace middleware is registered');
console.log(socket.request.headers.cookie);
if (socket.request.headers.cookie) {
socket.request.cookies = cookie.parse(decodeURIComponent(socket.request.headers.cookie));
socket.request.sessionID = socket.request.cookies['PHPSESSID'];
socket.request.socketSessionId = socket.request.cookies['socketSessionId'];
console.log("Authorization attempt with sessionID: " + socket.request.sessionID + " and socketSessionId: " + socket.request.socketSessionId);
redisClient.get("PHPREDIS_SESSION:" + socket.request.sessionID, function (error, reply) {
if (error) {
console.log("The redis client had an error: " + error);
return handler(new Error('The connection was refused because the redis client had an error.'));
} else if (!reply) {
console.log('The connection was refused because the redis client did not find the sessionID.');
return handler(new Error('The connection was refused because the redis client did not find the sessionID.'));
} else {
var redisSocketSessionId = utils.getRedisValue(reply, "socketSessionId");
if ('undefined' == typeof socket.request.socketSessionId || redisSocketSessionId != socket.request.socketSessionId) {
console.log('The connection was refused because the socketSessionId was invalid.');
return handler(new Error('The connection was refused because the socketSessionId was invalid.'));
} else {
console.log('The connection was granted.');
handler();
}
}
});
} else {
console.log('The connection was refused because no cookie was transmitted.');
return handler(new Error('The connection was refused because no cookie was transmitted.'));
}
});
The client connection:
<script type="text/javascript">
var elearningSocket;
$(function() {
if ('undefined' != typeof io && 'undefined' == typeof elearningSocket) {
console.log("Creating a socket on //dev.learnintouch.com:9001/elearning");
elearningSocket = io.connect('//dev.learnintouch.com:9001/elearning', { reconnect: true, rejectUnauthorized: false });
}
if ('undefined' != typeof elearningSocket) {
console.log("A socket on //dev.learnintouch.com:9001/elearning has been created");
elearningSocket.on('connect', function() {
console.log("The elearning namespace socket connected");
elearningSocket.emit('watchLiveCopilot', {'elearningSubscriptionId': '63', 'elearningClassId': '7'});
});
elearningSocket.on('postLogin', function(data) {
isAdmin = data.admin;
});
elearningSocket.on('message', function(message) {
console.log(message);
});
}
});
</script>
And the Chrome browser console:
Creating a socket on //dev.learnintouch.com:9001/elearning
A socket on //dev.learnintouch.com:9001/elearning has been created
But when sending a client connection, the log never shows the The namespace middleware is registered message.
Versions:
http#0.0.1-security
https#1.0.0
socket.io#4.1.3
cors#2.8.5
redis#3.1.2
socket.io-redis#6.1.1
connect#3.7.0
cookie#0.4.1
lodash#4.17.21
It looks like the connection cannot be established.
After a while the browser console shows an ERR_EMPTY_RESPONSE message as in:
socket.io.min.js:6 GET http://dev.learnintouch.com:9001/socket.io/?EIO=4&transport=polling&t=NbGNn6V net::ERR_EMPTY_RESPONSE
But the NodeJS socket server seems to be listening:
netstat -l | grep 9001
tcp6 0 0 [::]:9001 [::]:* LISTEN
The NodeJS socket server is not reachable.
But the firewall seems not to be the issue:
sudo ufw status verbose
Status: active
To Action From
-- ------ ----
9001 ALLOW IN Anywhere
The error can be seen live at
http://www.europasprak.com/elearning/subscription/2938/course
by first logging at
http://www.europasprak.com/engine/modules/user/login.php
with using the user demo#demo.com with the demo password.
UPDATE: I could solve the issue. It related to a handler preventing the connection from being established.
When changing the following:
module.exports.io.use((socket, handler) => {
to the following:
module.exports.io.of('/elearning').use((socket, handler) => {
the connection could then be done.
you need to determine whether the socket.io connection is successful, and then add events such as cores, adapters, events etc...to track down the problem step by step.
judging from the error report you provided above, socket.io was not established successfully.

Different behaviour between new tls.TLSSocket() followed by connect(..) versus tls.connect(..)

I'm attempting to use the following code to create a TLS Socket in nodejs
const socket = new net.Socket();
socket.setEncoding('utf8');
let tlsSocket = new tls.TLSSocket()
socket.on('connect', (connectionData) => {
// Do extra work with socket
tlsSocket.connect({
host: targetHost,
port: targetPort,
socket: socket,
})
}
and this is causing an ECONNREFUSED error. The events I see in this flow on tlsSocket are
lookup
error ECONNREFUSED
_tlsError
close
But if I change the code to
const socket = new net.Socket();
socket.setEncoding('utf8');
socket.on('connect', (connectionData) => {
// Do extra work with socket
let tlsSocket = tls.connect({
host: targetHost,
port: targetPort,
socket: socket,
})
}
It works with events on the tlsSocket
resume
data
readable
end
prefinish
finish
close
Why does this fail if I create the constructor version of the TLSSocket and connect it later. Rather than when I use tls.connect(..) which passes.
I need a reference to the tls socket to be returned before the socket connect event. Hence this is blocking me.

Errors with publishing messages to Amazon Queue using available node js libraries

I am trying to publish messages to Amazon MQ from Node JS and none of the libraries I have tried so far seem to be working.
Library 1:
stomp-client
Code:
var Stomp = require('stomp-client');
var destination = '/topic/{new_topic}';
var client = new Stomp('{prefix}.amazonaws.com',
61614,
'{user}',
'{password}');
client.connect(function(sessionId) {
client.publish(destination, 'Oh herrow');
});
Error with first library:
Emitted 'error' event at:
at StompFrameEmitter.<anonymous> (project_path\node_modules\stomp-client\lib\client.js:236:10)
at StompFrameEmitter.emit (events.js:182:13)
[... lines matching original stack trace ...]
at Socket.Readable.push (_stream_readable.js:219:10)
Library 2:
stompit
Code:
const stompit = require('stompit');
var connectOptions = {
'host': '{prefix}.amazonaws.com',
'port': 61614,
'connectHeaders':{
'host': '/',
'login': '{user}',
'passcode': '{password}',
'heart-beat': '5000,5000'
}
};
stompit.connect(connectOptions, function(error, client) {
if (error) {
console.log('connect error ' + error.message);
return;
}
var sendHeaders = {
'destination': '/topic/{new_topic}',
'content-type': 'text/plain'
};
var frame = client.send(sendHeaders);
frame.write('hello');
frame.end();
});
Error with second library: connect error unexpected end of stream
I am not sure what else I can try but I seem to be stuck here as the error messages are not even verbose plus there isnt a lot of information on this issue online.
Only relevant article I found has no answer on Amazon forum:
https://forums.aws.amazon.com/thread.jspa?messageID=831730&tstart=0
What worked for me to solve this issue was to set ssl connection to true as follows:
const server_options = {
host,
port,
ssl: true,
connectHeaders: {
host: '/',
'accept-version': '1.1',
'heart-beat': '0,0', // no heart beat
login: user,
passcode: pass,
},
};
Port must be set to 61614 for stomp+ssl connection.

Node 4.1.0 TLSSocket issues

Strange behavior in Node with TLSSocket and tls.connect.
var port = 7000;
var host = '94.125.182.252'; //freenode
var tls = require('tls');
var net = require('net');
var socket = new net.Socket();
var secure;
secure = new tls.TLSSocket( socket, {
isServer: false,
rejectUnauthorized: false
});
// edit (left out of original post, but present in my test code, whoops)
secure.connect( {
port: port,
host: host
});
secure.setEncoding( 'utf8' );
secure.on( 'connect' , function() {
console.log( 'connected' );
})
.on( 'secureConnect', function() {
console.log( 'secure connect' );
})
.on( 'error', function( e ) {
console.log( 'error', e );
})
.on( 'data', function( data ) {
console.log( data );
});
if ( secure.isPaused() ) {
console.log( 'socket was paused' );
secure.resume();
}
This doesn't even attempt to connect and no error messages are produced. I have wireshark monitoring and there is no activity captured.
A different approach:
secure = tls.connect( {
rejectUnauthorized: false,
host: host,
port: port,
socket: socket
});
Same story, nothing captured, no errors. If I remove the socket: socket aspect above it will connect. This makes some sense as the docs state that if the socket option is specified it will ignore port and host. The above works on my previous Node version( 0.12.7).
If I want to use the existing socket I have to tell it to connect before calling tls.connect.
socket.connect( {
port: port,
host: host
});
secure = tls.connect( {
rejectUnauthorized: false,
socket: socket
});
This doesn't seem proper.
Passing a connecting socket to tls.TLSSocket( socket, ...) seems to have no effect.
The 'connect' event is fired but I imagine that is not related to TLSSocket.
I could not get tls.TLSSocket(...) to work on previous Node iterations.
Stepping through with node debug did not expose any obvious problems.
The options for net.Socket([options]) don't seem to accept a port or host for configuring until you try to connect, and trying to connect before passing to tls.connect seems counter intuitive. It would suggest that is not the intended usage.
So my questions would be:
What am I doing wrong with tls.TLSSocket() or perhaps is it a bug?
Am I correct to assume that passing an existing socket into tls.connect() is for already established connections switching protocol? If not, whats the proper way to assign a port and host?
Edit:
As per suggestion:
secure = tls.connect( {
rejectUnauthorized: false,
socket: socket
});
socket.connect( {
port: port,
host: host
});
This works.
secure = new tls.TLSSocket( socket , {
isServer: false,
rejectUnauthorized: false
});
socket.connect( {
port: port,
host: host
});
Unfortunately this does not work. A 'connect' event is emitted, never a 'secureConnect' and never any other events or data.
In your first two (non-working) examples, you only created a socket and never started actually connected it. Add a socket.connect(); at the end of your original code and it should work fine.
tls.connect() when passed a plain socket, does not actually call socket.connect(); internally, it merely sets up to start listening for data on the socket so it can decrypt incoming data properly.

Socket.get callback not triggered in socket.on function

I've been stuck on this issue for a while the answer might be really basic but I fail to understand what the problem is. AFAIU It execute the function but doesnt trigger the callback and I dont know why.
My script aim to have both a tcp server to have a device (raspberry pi) that connect a tcp socket and a client to connect to a websocket on a sailsjs app.
I manage to have both this thing running on the following code, the problem is they only work separatly, simultanuously but separatly, when I try a get outside the socket everything works fine but when I do inside, the io.socket object is just piling up the get request in a requestQueue.
{ useCORSRouteToGetCookie: true,
url: 'http://localhost:1337',
multiplex: undefined,
transports: [ 'polling', 'websocket' ],
eventQueue: { 'sails:parseError': [ [Function] ] },
query:'__sails_io_sdk_version=0.11.0&__sails_io_sdk_platform=node&__sails_io_sdk_language=javascript',
_raw:
{ socket:
{ options: [Object],
connected: true,
open: true,
connecting: false,
reconnecting: false,
namespaces: [Object],
buffer: [],
doBuffer: false,
sessionid: '0xAlU_CarIOPQAGUGKQW',
closeTimeout: 60000,
heartbeatTimeout: 60000,
origTransports: [Object],
transports: [Object],
heartbeatTimeoutTimer: [Object],
transport: [Object],
connectTimeoutTimer: [Object],
'$events': {} },
name: '',
flags: {},
json: { namespace: [Circular], name: 'json' },
ackPackets: 0,
acks: {},
'$events':
{ 'sails:parseError': [Function],
connect: [Object],
disconnect: [Function],
reconnecting: [Function],
reconnect: [Function],
error: [Function: failedToConnect],
undefined: undefined } },
requestQueue:
[ { method: 'get', headers: {}, data: {}, url: '/', cb: [Function] },
{ method: 'get', headers: {}, data: {}, url: '/', cb: [Function] } ] }
The code is the following :
//library to connect to sailsjs websockets
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
//library to do the tcp server
var net = require('net');
// Instantiate the socket client (`io`)
// (for now, you must explicitly pass in the socket.io client when using this library from Node.js)
var io = sailsIOClient(socketIOClient);
// Set some options:
// (you have to specify the host and port of the Sails backend when using this library from Node.js)
io.sails.url = 'http://localhost:1337';
var server = net.createServer(function(tcpSocket) { //'connection' listener
//socket was sucessfully connected
console.log('client connected');
//notify on deconnection
tcpSocket.on('end', function() {
console.log('client disconnected');
});
// Handle incoming messages from clients.
tcpSocket.on('data', function (data) {
console.log(data.toString('utf8', 0, data.length));
//if data is PING respond PONG
if(data.toString('utf8', 0, 4)=='PING'){
console.log('I was pinged');
tcpSocket.write('PONG\r\n');
}
console.log(io.socket);//debugging purpose
//trigger a socket call on the sails app
io.socket.get('/', function (body, JWR) {
//display the result
console.log('Sails responded with: ', body);
console.log('with headers: ', JWR.headers);
console.log('and with status code: ', JWR.statusCode);
});
});
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
It looks like your socket isn't autoconnecting. Try connecting manually:
// Instantiate the socket client (`io`)
// (for now, you must explicitly pass in the socket.io client when using this library from Node.js)
var io = sailsIOClient(socketIOClient);
// Set some options:
// (you have to specify the host and port of the Sails backend when using this library from Node.js)
io.sails.url = 'http://localhost:1337';
var socket = io.sails.connect();
socket.on('connect', function() {
... connect TCP server and continue ...
});
I found a solution, I just got rid of sails.io.js and used plain socket.io it now works as intended feel free to explain though why it didnt in sails.io.js
//library to connect to sailsjs websockets
var socketIOClient = require('socket.io-client');
//var sailsIOClient = require('sails.io.js');
//library to do the tcp server
var net = require('net');
var socket=socketIOClient.connect('http://localhost:1337', {
'force new connection': true
});
var server = net.createServer(function(tcpSocket) { //'connection' listener
//socket was sucessfully connected
console.log('client connected');
//notify on deconnection
tcpSocket.on('end', function() {
console.log('client disconnected');
});
// Handle incoming messages from clients.
tcpSocket.on('data', function (data) {
console.log(data.toString('utf8', 0, data.length));
console.log(data.toString('utf8', 0, data.length));
//if data is PING respond PONG
if(data.toString('utf8', 0, 4)=='PING'){
console.log('I was pinged');
tcpSocket.write('PONG\r\n');
}
if(data.toString('utf8', 0, 4)=='test'){
socket.emit('test',{message : 'test'});
//io.socket.disconnect();
}
});
});

Resources