Node-osc sometimes sends OSC too often: related to IP address? - node.js

I have a local Node.js app on port localhost:3000. I'm using node-osc to message to MaxMSP. My code checks every 2 seconds if there is a reason to send the message (this is related to machine learning and webcam). 95 % of the time this works fine; OSC message might be sent now, then after 2 minutes, then after 10 seconds etc.
However, sometimes the OSC messaging goes crazy by sending a message every two seconds, despite my webcam and machine learning classifications staying the same. If there are no triggering changes, no messages should be sent. I have been thinking if this could be related to the fact that I sometimes change the location and respective IP address where my app functions. Could the system become unstable when switching between two IP addresses? I don't (yet at least) have proof that the "overheating" would come straight after changing the IP address.
Combining OSC with Node.js is new to me so I'm happy for any insights regarding the problem.
Some snippets:
server.js
const express = require("express");
var cors = require('cors');
const app = express();
let broadcaster;
const port = process.env.PORT || 3000;
const http = require("http");
const server = http.createServer(app);
const io = require("socket.io")(server);
const { Client, Message } = require('node-osc');
const client = new Client('xxx.xxx.x.x', 5000); // this IP I keep changing
socket.on("param", function(data) {
console.log(data);
let address = data.address;
client.send(address, data.val);
});
broadcast.js
if (newLabel== "a human" && newLabel !==oldLabel){ // checks this + other changes every 2 seconds
socket.emit("human");
sendParam ("/sound", 4);
}
function sendParam(adr, val) {
let data = {
address: adr,
val: val
};
socket.emit('param', data)
}

Related

Socket Io limiting only 6 connection in Node js

So i came across a problem.I am trying to send {id} to my rest API (node js) and in response, I get data on the socket.
Problem:
For first 5-6 time it works perfectly fine and display Id and send data back to socket.But after 6 time it does not get ID.
I tried this https://github.com/socketio/socket.io/issues/1145
and https://github.com/socketio/socket.io/issues/1145 but didn't solve the problem.
On re compiling the server it shows previous {ids} which i enter after 6 time.it like after 5-6 time it is storing id in some form of cache.
Here is my API route.
//this route only get {id} 5-6 times .After 5-6 times it does not display receing {id}.
const express = require("express");
var closeFlag = false;
const PORT = process.env.SERVER_PORT; //|| 3000;
const app = express();
var count = 1;
http = require('http');
http.globalAgent.maxSockets = 100;
http.Agent.maxSockets = 100;
const serverTCP = http.createServer(app)
// const tcpsock = require("socket.io")(serverTCP)
const tcpsock = require('socket.io')(serverTCP, {
cors: {
origin: '*',
}
, perMessageDeflate: false
});
app.post("/getchanneldata", (req, res) => {
console.log("count : "+count)
count++;// for debugging purpose
closeFlag = false;
var message = (req.body.val).toString()
console.log("message : "+message);
chanId = message;
client = dgram.createSocket({ type: 'udp4', reuseAddr: true });
client.on('listening', () => {
const address = client.address();
});
client.on('message', function (message1, remote) {
var arr = message1.toString().split(',');
}
});
client.send(message, 0, message.length, UDP_PORT, UDP_HOST, function (err, bytes) {
if (err) throw err;
console.log(message);
console.log('UDP client message sent to ' + UDP_HOST + ':' + UDP_PORT);
// message="";
});
client.on('disconnect', (msg) => {
client.Diconnected()
client.log(client.client)
})
}
);
There are multiple issues here.
In your app.post() handler, you don't send any response to the incoming http request. That means that when the browser (or any client) sends a POST to your server, the client sits there waiting for a response, but that response never comes.
Meanwhile, the browser has a limit for how many requests it will send simultaneously to the same host (I think Chrome's limit is coincidentally 6). Once you hit that limit, the browser queues the request and and waits for one of the previous connections to return its response before sending another one. Eventually (after a long time), those connections will time out, but that takes awhile.
So, the first thing to fix is to send a response in your app.post() handler. Even if you just do res.send("ok");. That will allow the 7th and 8th and so on requests to be immediately sent to your server. Every incoming http request should have a response sent back to it, even if you have nothing to send, just do a res.end(). Otherwise, the http connection is left hanging, consuming resources and waiting to eventually time out.
On a separate note, your app.post() handler contains this:
client = dgram.createSocket({ type: 'udp4', reuseAddr: true });
This has a couple issues. First, you never declare the variable client so it becomes an implicit global (which is really bad in a server). That means successive calls to the app.post() handler will overwrite that variable.
Second, it is not clear from the included code when, if ever, you close that udp4 socket. It does not appear that the server itself ever closes it.
Third, you're recreating the same UDP socket on every single POST to /getchanneldata. Is that really the right design? If your server receives 20 of these requests, it will open up 20 separate UDP connections.

How to assign a random port number to a gRPC server instance (in Node)?

When starting an http server in Node.js, developers can listen on a randomly available port by passing 0 like so:
const http = require('http')
const service = require('../my/service);
const server = http.createServer(service)
server.listen(process.env.PORT || 0) // <-- Random port by default!
I wonder how I can do the same thing with gRPC? Something like...
const grpc = require('grpc')
const services = require('./service_grpc_pb')
const server = new grpc.Server()
server.addService(services.MyService, { ... })
server.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure())
server.start()
Does that work? I've yet to find out. My goal is to get a random port and then query the server to get the assigned port in order to register the service with a central microservice registry.
Thanks for your help in advance.
Yes, you can use a port number of 0 to assign a random port to a gRPC server. The server.bind method returns the port number that was actually assigned. If you want to use the bindAsync method instead, the assigned port number will be passed to the callback.

Websocket closes on client message [JavaScript/Node.js]

I'm creating a simple Node.js WebSocket server, but I am running into a problem after the initial handshake.
In the beginning, I was only using chrome and the command line to monitor back and forth between a HTML5 Websocket and the Node.js server. It took a bit to implement the protocol, but I had just finished a very basic version of the server-side message decoding. I was having a hard time, however, because whenever I would call ws.send('some kind of message'), the websocket would close on the client side. Looking into the network tab of the DevTools, it looks like the message would send from the client, and get an immediate error response of (Opcode -1), and would log this error in the console:
WebSocket connection to 'ws://localhost:4000/' failed: A server must not mask any frames that it sends to the client.
I've looked into what it all means, and I can't figure out why my code would throw it. I had tried rebuilding it, and also making a test message send after the confirmation, which worked. The only thing I had not tried was using a different browser, so I tried it today. And it worked as expected.
Below is all my relevant code.
Libraries, constants, and listens:
const hostname = 'localhost';
const webport = 8080;
const socketport = 4000;
const http = require('http');
const net = require('net');
const mysql = require('mysql');
const rlm = require('readline');
const crypt = require('crypto');
...
server.listen(webport,hostname);
socketServer.listen(socketport,hostname);
HTTP Server:
const server = http.createServer(
function(req,res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write("
<html>
<head>
<title>Test Title</title>
</head>
<body>
<h1>Here's the thing</h1>
<p>im baby</p>
</body>
<script>
const ws = new WebSocket('ws://"+hostname+":"+socketport+"');
ws.addEventListener('message',function(data){
console.log(data.data)
});
</script>
</html>
"); // Reformatted for better reading
res.end();
});
Net Server:
var sockets = new Map();
var socketInfo = {};
const socketDelimiters = {
'Accept-Encoding':',',
'Accept-Language':';',
'Sec-WebSocket-Extensions':'; '
}
const socketServer = net.Server(function(s) {
s.on('data',function(e) {
/*
* If the socket is not registered, read first message as
* the beginning to a handshake
*/
if(sockets.get(s)==null) {
var str = ""+e;
var tempobj = str.split("\r\n");
var newObj = {};
for(var i in tempobj) {
if(tempobj[i].length>0) {
var tempProperty = tempobj[i].split(': ');
if(tempProperty.length>1) {
if(socketDelimiters[tempProperty[0]]!=null){
tempProperty[1] = tempProperty[1].split(
socketDelimiters[tempProperty[0]]);
}
newObj[tempProperty[0]] = tempProperty[1];
} else {
newObj.header = tempProperty;
}
}
}
var protocolReturn = "
HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-Websocket-Accept: "+createAcceptKey(newObj['Sec-WebSocket-Key'])
+"\r\n\r\n"; //Reformatted for better reading
s.write(protocolReturn);
s.pipe(s);
sockets.set(s,newObj['Sec-WebSocket-Key']);
socketInfo[newObj['Sec-WebSocket-Key']] = {
socket:s,
isReading:false,
message:null,
mask:null,
handshake: newObj
};
s.write(Buffer.from([0x81,0x04,0x74,0x65,0x73,0x74])); // 'test'
s.pipe(s);
} else {
/*
* If the socket is found and registered, decode the incoming message
*/
var firstBytes = e.readUInt16BE(0);
console.log(firstBytes);
var length=((firstBytes & 0x007F)/0x0001);
var FIN = ((firstBytes & 0x8000))!=0;
var opcode = (firstBytes & 0x0F00)/0x0100;
var mask = ((firstBytes & 0x0080)!=0);
if(opcode!=8) {
console.log("end: "+FIN);
console.log("mask: "+mask);
console.log("op code: "+opcode);
console.log("length: "+length);
var mask = [];
for(var i=0; i<4; i++) {
var b = e.readUInt8(2+i);
mask.push(b);
}
var val=[];
for(var i=0; i<length; i++) {
var b = e.readUInt8(6+i) ^ mask[i%4];
val.push(b);
}
var newVal = new Buffer.from(val);
console.log(newVal.toString('utf8'));
}
}
})
// Handles error
s.on('error',function(err) {
console.log(err);
})
// Takes socket out of the socket list on close
s.on('close',function(hasError) {
if(hasError) {console.log("Please see error")}
delete socketInfo[sockets.get(s)];
sockets.delete(s);
});
});
// Generates accept key from given key
function createAcceptKey(key) {
var inKeyHash = crypt.createHash('sha1');
inKeyHash.update(key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
return (inKeyHash.digest('base64'));
}
What all this should do ('<' means server to client, '>' means client to server)
> [handshake initiation]
< [handshake confirmation]
< test
> [anything the client sends through the console]
/*
*All I do for the client to server bit at the end is go into the console,
* and plug in something like this
*/
ws.send('blah blah blah')
This works perfectly fine in Firefox, but as explained above, in chrome, it throws an error, claiming that the server had sent a masked frame at the same instant the client sends a message to the server.
Is there a reason that chrome reads a masked frame and firefox does not?
UPDATE:
I have now tried to use this in a different browser (the OBS browser to be exact) and it throws the same error on the server's side that connecting with Chrome does (I've added an event listener to send a message on socket open on the client side). Would anyone know why it only works in Firefox?
Solved this two days ago, didn't realize I could post my own answer (still new to posting here, sorry!)
A lot of my understanding of Node.js sockets came from the net documentation. In this, there is an example of a server and client interaction. The pipe() command is used after writing on the server side, so I assumed that it was necessary in writing to a socket client.
It is not required, and in fact should not be used. The example is an echo server, so every message the client sends to the server will be relayed back to the client. This post is the one that helped me with this, but I am a bit mad, because I tried following that advice before, and it stopped working when I removed the pipe commands. If the definition of insanity is "Trying something again and expecting different results," then throw me in the loony bin.
TL,DR;
Writing to the socket was easier than I thought:
// Expected:
socket.write('blah blah blah');
socket.pipe(socket);
// Reality
socket.write('blah blah blah');

My node socket.io connection get automatically disconnect after a short period of inactivity

I have spent a long on Google but I didn't found any solution. I saw many questions related to my problem on stack overflow but I didn't get any solution.
Explaining in brief, I am coding for real time chat room and it works fine when I continuously send messages from either room but when I left it for a short period mean (when message is not send from either side) it automatically gets disconnect inside the browser is still opened. And messages send from one room didn't transferred to other room. Please help me.
var express = require('express'); // node code
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var redis = require('redis');
var redis_client = redis.createClient(6379,'192.168.43.49');
redis_client.auth('rajesh');
redis_client.select(1);
io.sockets.on('connection',function(socket){
/* used for transfering message from one node to other node */
socket.on('node_message',function(data){
// sending message to other end
redis_client.smembers(data.user_hash,function(err,reply){
if(reply!=null){
reply.forEach(function(value){
var res = {'user_hash':socket.user_hash,'msg':data.msg};
io.to(value).emit('node_message',res); // i am sending sender user_hash also so that while getting message in second end i will validate second party {cause problem in multi-page to show message in every panel}
});
}
});
});
socket.on('disconnect', function (){
console.log('lost connection',socket.user_hash);
})
});

Connecting to Websocket in OpenShift Online Next Gen Starter

I'm in the process of trying to get an application which I'd built on the old OpenShift Online 2 free service up and running on the new OpenShift Online 3 Starter, and I'm having a bit of trouble.
The application uses websocket, and in the old system all that was required was for the client to connect to my server on port 8443 (which was automatically routed to my server). That doesn't seem to work in the new setup however - the connection just times out - and I haven't been able to find any documentation about using websocket in the new system.
My first thought was that I needed an additional rout, but 8080 is the only port option available for routing as far as I can see.
The app lives here, and the connection is made on line 21 of this script with the line:
this.socket = new WebSocket( 'wss://' + this.server + ':' + this.port, 'tabletop-protocol' );
Which becomes, in practice:
this.socket = new WebSocket( 'wss://production-instanttabletop.7e14.starter-us-west-2.openshiftapps.com:8443/', 'tabletop-protocol' );
On the back end, the server setup is unchanged from what I had on OpenShift 2, aside from updating the IP and port lookup from env as needed, and adding logging to help diagnose the issues I've been having.
For reference, here's the node.js server code (with the logic trimmed out):
var http = require( "http" );
var ws = require( "websocket" ).server;
// Trimmed some others used by the logic...
var ip = process.env.IP || process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var port = process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 8080;
/* FILE SERVER */
// Create a static file server for the client page
var pageHost = http.createServer( function( request, response ){
// Simple file server that seems to be working, if a bit slowly
// ...
} ).listen( port, ip );
/* WEBSOCKET */
// Create a websocket server for ongoing communications
var wsConnections = [];
wsServer = new ws( { httpServer: pageHost } );
// Start listening for events on the server
wsServer.on( 'request', function( request ){
// Server logic for the app, but nothing in here ever gets hit
// ...
} );
In another question it was suggested that nearly anything - including this -
could be related to the to the ongoing general issues with US West 2, but other related problems I was experiencing seem to have cleared, and that issue has been posted for a week with no update, so I figured I'd dig deeper into this on the assumption that it's something I'm doing wrong instead of them.
Anyone know more about this and what I need to do to make it work?

Resources