Handling Node.js socket data - javascript

I have server receiving data from a client [GPS Device]. I have problem presenting the data (i.e the results obtained from the client) in a readable format. Below are the things I have tried.
Doing:
console.log(data)
I get
<Buffer d0 d7 3d 00 c4 56 7e 81>
Also tried
console.log(data.toString())
But I get unwanted results:See below:
��A�V~�
Here is my full code:
var net = require('net');
var fs = require('fs');
var server = net.createServer(function (socket) {
console.log('Server started: Waiting for client connection ...');
console.log('Client connected:port,address: '+socket.remotePort, socket.remoteAddress);
socket.on('data', function (data) {
var date = new Date();
var today = date.getDate()+'_'+date.getMonth();
fs.appendFile(today+'_log.txt', data, function (err) {
if (err) throw err;
console.log(data.toString())
});
});
});
server.listen(my_port, my_ip);
Thanks for your input.

According to the documentation, you must specify an encoding to get a String instead of a Buffer:
Event: 'data'#
Buffer object
Emitted when data is received. The argument data will be a Buffer or String. Encoding of data is set by socket.setEncoding().
You could configure the socket to get the data in UTF-8, for example, with:
socket.setEncoding('utf8');

Assuming the data in buffer is 7 bit ASCII,
console.log(data.toString('ascii'))
would resolve the problem.

Do it like this
socket.on('data', function (data) {
var buff = Buffer.from(data);
But remember, lots of GPS devices use little-endian, so later you're going to have to decode the data as well.

Related

How do I get my server to return the right Sec-WebSocket-Accept header value?

I seem to be getting the wrong hash value given the key through my webSocket. From what I can tell, the client side of the socket works, because when I have it connect to other servers, it's successful.
index.js
const http = require('http')
const cryp=require('crypto')
const port = 8080
var ourHTML=require('fs').readFile("index.html",(err,data) => {
if(err) throw err;
ourHTML = data.toString();
});
const requestHandler = (request, response) => {
//console.log(request)
response.end(ourHTML)
}
const server = http.createServer(requestHandler)
server.on('upgrade',(req,socket)=>{
if(req.headers['upgrade'] !== 'websocket'){
socket.end('HTTP/1.1 400 Bad Request');
return;
}
const hash=getAVal(req.headers['sec-websocket-key']);
console.log(hash);
socket.write([
"HTTP/1.1 101 Web Socket Protocol Handshake",
"Upgrade: WebSocket",
"Connection: Upgrade",
`Sec-WebSocket-Accept: ${hash}`
].join('\r\n')+'\r\n\r\n');
//socket.end();
});
function getAVal(key){
console.log(key);
return cryp
.createHash('sha1')
.update(key+'258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'binary')
.digest('base64');
}
server.listen(port, (err) => {
if(err){
return console.log("Uhh ohh, "+err.stack,err)
}
console.log("server listening at "+port)
})
index.html
<html>
<head><title>Local Server</title></head>
<body><h1>Local Server Body</h1><p id="p">To Change</p></body>
<script>
console.log("here");
var ws=new WebSocket("ws://10.0.0.150:8080");
//var ws=new WebSocket("wss://echo.websocket.org");
setInterval(req,1000);
function req(){
ws.send("tickReq");
}
ws.addEventListener('open', () => {
ws.send("Hello");
});
ws.addEventListener('message', event => {
document.getElementById("p").innerHTML=event.data;
});
</script>
</html>
An example for a key and hash pair when running is:
PxsrStN1CGLK/JBYydUFjg==
QAK+TE6u+sV705GI+LpP4yKM04Y=
The top is the key given by the browser, and the bottom is what the getAVal function is returning, and it being incorrect causing this message.
Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value
In your example, the base64 string
"QAK+TE6u+sV705GI+LpP4yKM04Y="
decodes to bytes
4002BE4C4EAEFAC57BD39188F8BA4FE3228CD386
However, the correct SHA1 hash for the string
"PxsrStN1CGLK/JBYydUFjg==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
is bytes
2FEA5BE3299C27C3DD290853435C7529BBBC0F0F
and the base64 encoded form of those bytes is
"L+pb4ymcJ8PdKQhTQ1x1Kbu8Dw8="
Which means your SHA1 hash is wrong to begin with.
Try calling digest() without an encoding specified so you can get a Buffer instead of a string, and then verify it matches the bytes above.
Then convert those bytes to base64 using Buffer.toString("base64") and verify it matches the string above.

Buffer not recognized as buffer on nodejs with sails js

I'm trying to get the buffer from a blob being sent to my SailsJs server.
An example of what is being sent to the server is this:
Blob(3355) {size: 3355, type: "video/x-matroska;codecs=avc1,opus"}
Once on the server side, I do the following:
let body = new Array(0);
let buffer;
let readable = req.file('recordingPart');
readable.on('data', (chunk) => {
body.push(new Buffer(chunk));
});
readable.on('end', () => {
buffer = Buffer.concat(body);
console.log('There will be no more data.', buffer.length, buffer);
});
When running this part of the code I get the error:
buffer.js:226
throw new errors.TypeError(
^
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, buffer, arrayBuffer, array, or array-like object. Received type object
at Function.from (buffer.js:226:9)
at new Buffer (buffer.js:174:17)
...
In this case the error is at the body.push(new Buffer(chunk)); on new Buffer(chunk)
My first approach was similar:
let body = [];
let buffer;
let readable = req.file('recordingPart');
readable.on('data', (chunk) => {
body.push(chunk);
});
readable.on('end', () => {
buffer = Buffer.concat(body);
console.log('There will be no more data.', buffer.length, buffer);
});
but I've got this error:
buffer.js:475
throw kConcatErr;
^
TypeError [ERR_INVALID_ARG_TYPE]: The "list" argument must be one of type array, buffer, or uint8Array
at buffer.js:450:20
In this one the error pops at Buffer.concat(body);
I got some guidance from this answer Node.js: How to read a stream into a buffer?
Can anyone help me in getting the buffer from that req.file.
You can get uploadedFile as below.
req.file('recordingPart').upload(function (err, uploadedFiles){
if (err) return res.serverError(err);
// Logic with uploadedFiles goes here
});
You can get file descriptor from uploadedFiles[0].fd and use it to read/stream the file as below.
fs.readFile(uploadedFiles[0].fd, 'utf8', function (err,data) {
// Logic with data goes here
var myBuffer = Buffer.from(data);
});
To use fs as above create fs instance as below.
var fs = require('fs');
Your current upload approach will work but there's another new way you might want to consider:
// Upload the image.
var info = await sails.uploadOne(photo, {
maxBytes: 3000000
})
// Note: E_EXCEEDS_UPLOAD_LIMIT is the error code for exceeding
// `maxBytes` for both skipper-disk and skipper-s3.
.intercept('E_EXCEEDS_UPLOAD_LIMIT', 'tooBig')
.intercept((err)=>new Error('The photo upload failed: '+util.inspect(err)));
Full Example Here
Also check out the Sails.JS Platzi Course for video tutorials on this latest upload functionality using the example project Ration.

Sending binary data over websocket with cowboy and MessagePack

I'm trying to send a MessagePack-encoded message from Cowboy to a browser over WebSocket, and received data is always empty or invalid. I'm able to send binary data from JS to my cowboy handler, but not vice versa.
I'm using Cowboy 1.0.4 with official msgpack-erlang application. I also use msgpack-lite for my in-browser javascript.
Examples:
websocket_handler:
websocket_handle({text, <<"return encoded">>}, Req, State) ->
%% sends encoded message to client. Client is unable to decode and fails
{reply, {binary, msgpack:pack(<<"message">>)}, Req, State};
websocket_handle({binary, Encoded}, Req, State) ->
%% Works as expected
lager:info("Received encoded message: ~p", [msgpack:unpack(Encoded)]),
{ok, Req, State};
JS:
var host = "ws://" + window.location.host + "/websocket";
window.socket = new WebSocket(host);
socket.binaryType = 'arraybuffer';
socket.onmessage = function(event) {
var message = msgpack.decode(event.data);
console.log(message);
};
Browser returns an error inside msgpack.min.js:
Error: Invalid type: undefined
...ion n(t){var r=i(t),e=f[r];if(!e)throw new Error("Invalid type: "+(r?"0x"+r.toSt...
If I try to output raw event.data to console, here's what I'm getting:
ArrayBuffer {}
It seems to be empty for some reason. I'm new both to erlang and msgpack, and don't know what is going wrong. Thanks for your help!
Found the reason of my problem.
The way how I tried to decode message on the client was wrong:
socket.onmessage = function(event) {
var message = msgpack.decode(event.data);
console.log(message);
};
The right way:
socket.onmessage = function(event) {
var raw_binary_data = new Uint8Array(event.data);
var message = msgpack.decode(raw_binary_data);
console.log(message);
};
It seems like msgpack-lite doesn't support binary type. Try pack your data as a string.
{binary, msgpack:pack("message", [{enable_str, true}])}
Using Uint8Array is a valid solution for client side issue. On server to pack strings use:
msgpack:pack(<<"message">>,[{pack_str,from_binary}])
Source : Article

Stream ArrayBuffer websocket binary.js

I want so stream a lot of ArrayBuffers.
Sending Strings from the client to the server and back is no problem!
Sending ArrayBuffer to the Server is no Problem
Sending an ArrayBuffer from server to client is not working. I get an empty ArrayBuffer on the client => ArrayBuffer{}
Server:
var server = BinaryServer({port: 9000});
server.on('connection', function(client){
client.on('stream', function(stream, meta){
console.log(meta);
stream.on('data', function(data){
//console.log(data);
stream.write(data);
});
});
});
the console.log(data) shows me the filled array, so this works.
Client:
var wsStream = null;
var client = BinaryClient('ws://localhost:9000');
client.on('open', function(){
wsStream = client.createStream("audio");
wsStream.on('data', function(data){
console.log(data);
});
});
this logs: ArrayBuffer {}
so no data :(
I send the data with: wsStream.write(arrayBuffer);
If i send some array wsStream.write([0,2]); or some string wsStream.write("Hello"); I have no problem and get all my data back.
why is this happening ? thanks :)
Problem solved by setting binaryType to arraybuffer.
var myWebSocket = new WebSocket("ws://127.0.0.1");
myWebSocket.binaryType = "arraybuffer";

NodeJS HTTP request POST ERROR socket hang up

Hi I'm having problems to perform HTTP request on NodeJS given a larger number array of json object. The request works fine given small array of json object. However, if I try to increase the size array of json, I received Error: socket hang up {"error":{"code":"ECONNRESET"}}. Is it required to perform multiple write? Or is it something wrong going on at the other end?
Thanks in advance for taking your time here!
// data is a json object
var post_data = JSON.stringify(data);
var buf = new Buffer(post_data);
var len = buf.length;
var options = {
hostname: address,
port: port,
path: pathName,
method: 'PUT',
headers: {
'Content-Type':'application/json',
'Content-Length': len,
'Transfer-Encoding':'chunked'
}
};
// http call to REST API server
var req = restHttp.request(options, function(res) {
console.log('server PUT response received.');
var resData = '';
res.on('data', function(replyData) {
// Check reply data for error.
console.log(replyData.toString('utf8'));
if(replyData !== 'undefined')
resData += replyData;
});
res.on('end', function() {
callback(JSON.parse(resData));
});
});
req.write(buf);
req.end();
You can stream the request body.
If the data in buf was in a readable stream then you can just do buf.pipe(req).
For example, if the current directory contains a file data.json with the JSON you can do
var buf = fs.createReadStream(__dirname + '/data.json');
to create a ReadStream object. Then you can pipe this to you req
buf.pipe(req);
The pipe command will call req.end once its done streaming.

Categories

Resources