Chrome.serial how to read the data arrived? - javascript

After struggling a lot (more then a week Google chrome - chrome.serial connection failed), i have found that on OSX 10.11 Chrome.serial does not work because OSX refuse Chrome.serial if its not using native OSX way of connection requests .
Then i moved to Windows OS with following code and its working. But i am failing to read the data in readable format, can anyone please help?
var serial_port = "COM3";
var connectionId = -1;
var csv = null;
var serial = chrome.serial;
// 1 - Device Query
serial.getDevices(function(ports) {
for (var i=0; i<ports.length; i++) {
console.log('OK: DEVICES', ports[i].path);
csv = csv + ports[i].path;
}
});
// 2 - Connect and listen
serial.connect(serial_port, {bitrate: 9600}, function(connectionInfo) {
console.log('OK: CONNECTED', connectionInfo.connectionId);
connectionId = connectionInfo.connectionId;
serial.onReceive.addListener(function(receiveInfo) {
if (receiveInfo.connectionId !== connectionId) {
console.log("FAIL: connectionId mismatch");
return;
}
console.log(receiveInfo.data);
});
});
// 3 - Sync - WebPage
chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse) {
console.log('OK: WEB-PAGE ARRIVED');
});
Output:
How do i get the value as readable format instead of ArrayBuffer {} ?

Is this OK? (please improve the code if you can)
var serial_port = "COM3";
var connectionId = -1;
var csv = null;
var serial = chrome.serial;
var lineBuffer = "";
var ab2str = function(buf) {
var bufView = new Uint8Array(buf);
var encodedString = String.fromCharCode.apply(null, bufView);
return decodeURIComponent(escape(encodedString));
};
// 1 - Device Query
serial.getDevices(function(ports) {
for (var i=0; i<ports.length; i++) {
console.log('OK: DEVICES', ports[i].path);
csv = csv + ports[i].path;
}
});
// 2 - Connect and listen
serial.connect(serial_port, {bitrate: 9600}, function(connectionInfo) {
console.log('OK: CONNECTED', connectionInfo.connectionId);
connectionId = connectionInfo.connectionId;
serial.onReceive.addListener(function(receiveInfo) {
if (receiveInfo.connectionId !== connectionId) {
console.log("FAIL: connectionId mismatch");
return;
}
lineBuffer += ab2str(receiveInfo.data);
console.log(lineBuffer);
});
});
// 3 - Sync - WebPage
chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse) {
console.log('OK: WEB-PAGE ARRIVED');
});

Related

CefSharp browser weird behaviour

I've got a problem with my web-scraper. It should execute a javascript to make some changes on a webpage, then download the source and extract some specific data.
bool working = true;
for(int i = 0; i < urls.Count(); ++i)
{
working = true;
ChromiumWebBrowser scraper = new ChromiumWebBrowser(urls[i]);
scraper.FrameLoadEnd += scrape;
while(working)
{
Application.DoEvents();
System.Threading.Thread.Sleep(50);
}
}
async void scrape(object sender, FrameLoadEndEventArgs args)
{
ChromiumWebBrowser chrome = (ChromiumWebBrowser)sender;
if (args.Frame.IsMain && chrome.CanExecuteJavascriptInMainFrame)
{
string script = Properties.Resources.script;
chrome.ExecuteScriptAsync(script);
string data = " ";
do
{
string html = await chrome.GetSourceAsync();
string dataField = "data";
int dataFieldIndex = html.IndexOf(phoneField);
data = html.Substring(dataFieldIndex + dataField.Count(), html.IndexOf("<", dataFieldIndex + dataField.Count()) - dataFieldIndex - dataField.Count());
System.Threading.Thread.Sleep(50);
} while (data.Count() == 3);
addDataToHashSet(data);
}
else
{
Debug.WriteLine("Error");
}
}
private void addDataToHashSet(string data)
{
data = data.Replace("-", "");
data = data.Replace(" ", "");
dataHashSet.Add(data);
working = false;
}
Unfortunately, it's unpredictable. It hangs after few iterations - a proper event with CanExecuteJavascriptInMainFrame and IsMain is never triggered for some iterations. Could you explain it to me?
[edit]: My Cef initialization below:
CefSettings cefSettings = new CefSettings();
cefSettings.CefCommandLineArgs.Add("allow-running-insecure-content", "1");
cefSettings.IgnoreCertificateErrors = true;
CefSharpSettings.Proxy = new ProxyOptions(ip: "...", port: "...");
Cef.Initialize(cefSettings);

How do I test my WebSocket which is developed in JavaScript

I have created WebSocket.js but unfortunately I am unable to test it due to unavailability of data. The requirement is the data comes from various sources so I have multiple sockets for that. Note: I want to particularly test my socket.onMessage behaves for different sockets. Please find the code snippet below:
var webSocket;
var txQueue = [];
var defaultReconnectTimeout = 1000; //will be multiplied by 2 and saved into reconnectTimeout on each try
var reconnectTimeout = defaultReconnectTimeout;
var registerWebSocketHandlers = function(webSocket) {
webSocket.onclose = function(){
setTimeout(service.reopen, reconnectTimeout *= 2);
};
webSocket.onopen = function(e) {
reconnectTimeout = defaultReconnectTimeout; //reset this
deferredSend();
};
webSocket.onerror = function(e) {
throw new Error("[WebSocket] An error occured " + e);
};
}
var uniqid = function() {
return (new Date().getTime()).toString(16);
}
var deferredSend = function() {
if(!service.isOpen()) {
$timeout(deferredSend, 100);
return;
}
while(txQueue.length && service.isOpen()) {
var payload = txQueue.shift();
webSocket.send(typeof payload === 'string' ? payload : JSON.stringify(payload));
}
};
var createNewWebSocketInstance = function(apiUrl){
var websocket = new $window.WebSocket(apiUrl);
websocket.id = uniqid();
return websocket;
}
// TODO: this is a bit hacky since we directly bind it to the raw window event
$window.onbeforeunload = function(e) {
service.close();
};
var service = {};
service.setMessageEventHandler = function(name,cb) {
instances[name].onmessage = function(msg) {
if(msg.data.indexOf('Status: connected') === 0)
{
return;
}
var jsonObj = JSON.parse(msg.data);
cb(jsonObj);
};
};
service.isOpen = function() {
return webSocket.readyState === 1;
};
service.send = function(msg) {
txQueue.push(msg);
deferredSend();
};
service.close = function() {
return webSocket.close();
};
service.reopen = function() {
// get old message handler
var msgHandler = webSocket.onmessage;
// try closing the previous WebSocket
service.close();
// open new WebSocket
openConnection();
// re-attach old handler to new WebSocket
webSocket.onmessage = msgHandler;
};
service.getId = function() {
return webSocket.id;
}
// Returns an already existing instance of the socket, if unavailable then creates a new one.
service.getInstance = function(name, config) {
if(!(name in instances)) {
instances[name] = createNewWebSocketInstance(config);
}
registerWebSocketHandlers(instances[name]);
return instances[name];
};
return service;
You can test WebSocket using websocket.html at websocket.org Echo Test Creating your own test
Using a text editor, copy the following code and save it as
websocket.html somewhere on your hard drive. Then simply open it in a browser. The page will automatically connect, send a message,
display the response, and close the connection.
See Linux - WebSocket test error.

Express render broken after save to firebase

I am writing an express app to generate a google map from geo coordinates out of photos. I am attempting to use firebase to save data about the images. The code is fully working except when I save the photo data to firebase it breaks the map rendering on the next page showing connection errors to all my local files in the console like so
So the page is rendering but the map doesn't load and nor do the images. The data I am saving to firebase is actually saving though, and If I remove the function that saves the data to firebase everything works as expected. I think it may have something to do with the way the response is being pushed but I am at a loss. In any other page where I am saving data to firebase it works fine.
Here is the code for the route that is generating the photo data and saving it to firebase:
var express = require('express');
var router = express.Router();
var util = require('util');
var fs = require('fs');
var im = require('imagemagick');
var stormpath = require('express-stormpath');
var _ = require('lodash')
var Firebase = require('firebase');
router.post("/:campaignId", stormpath.loginRequired, function(req, res, next) {
function gatherImages(files, callback) {
//accept single image upload
if (!_.isArray(files)) {
files = [files];
}
var uploads = [];
var count = 0;
files.forEach(function(file) {
fs.exists(file.path, function(exists) {
if (exists) {
var name = req.body[file.originalname];
console.log(name);
var path = file.path;
var upFile = file.name;
uploads.push({
file: upFile,
imgPath: path,
caption: name || 'no comment'
});
count++;
}
if (files.length === count) {
callback(uploads);
}
});
});
}
function getGeoLoc(path, callback) {
im.readMetadata('./' + path, function(error, metadata) {
var geoCoords = false;
if (error) throw error;
if (metadata.exif.gpsLatitude && metadata.exif.gpsLatitudeRef) {
var lat = getDegrees(metadata.exif.gpsLatitude.split(','));
var latRef = metadata.exif.gpsLatitudeRef;
if (latRef === 'S') {
lat = lat * -1;
}
var lng = getDegrees(metadata.exif.gpsLongitude.split(','));
var lngRef = metadata.exif.gpsLongitudeRef;
if (lngRef === 'W') {
lng = lng * -1;
}
var coordinate = {
lat: lat,
lng: lng
};
geoCoords = coordinate.lat + ' ' + coordinate.lng;
console.log(geoCoords);
}
callback(geoCoords);
});
}
function getDegrees(lat) {
var degrees = 0;
for (var i = 0; i < lat.length; i++) {
var cleanNum = lat[i].replace(' ', '');
var parts = cleanNum.split('/');
var coord = parseInt(parts[0]) / parseInt(parts[1]);
if (i == 1) {
coord = coord / 60;
} else if (i == 2) {
coord = coord / 3600;
}
degrees += coord;
}
return degrees.toFixed(6);
}
function processImages(uploads, callback) {
var finalImages = [];
var count = 0;
uploads.forEach(function(upload) {
var path = upload.imgPath;
getGeoLoc(path, function(geoCoords) {
upload.coords = geoCoords;
finalImages.push(upload);
count++;
if (uploads.length === count) {
callback(finalImages);
}
});
});
}
function saveImageInfo(finalImages, callback) {
var campaignId = req.param('campaignId');
var user = res.locals.user;
var count = 0;
var campaignPhotosRef = new Firebase('https://vivid-fire-567.firebaseio.com/BSB/userStore/' + user.username + '/campaigns/' + campaignId + '/photos');
finalImages.forEach(function(image) {
campaignPhotosRef.push(image, function(err) {
if (err) {
console.log(err);
} else {
count++;
if (finalImages.length === count) {
callback(finalImages);
} else {
return;
}
}
});
});
}
if (req.files) {
if (req.files.size === 0) {
return next(new Error("Why didn't you select a file?"));
}
gatherImages(req.files.imageFiles, function(uploads) {
processImages(uploads, function(finalImages) {
saveImageInfo(finalImages, function(finalImages) {
var campaignId = req.param('campaignId');
console.log(res.req.next);
res.render("uploadMapPage", {
title: "File(s) Uploaded Successfully!",
files: finalImages,
campaignId: campaignId,
scripts: ['https://maps.googleapis.com/maps/api/js?key=AIzaSyCU42Wpv6BtNO51t7xGJYnatuPqgwnwk7c', '/javascripts/getPoints.js']
});
});
});
});
}
});
module.exports = router;
This is the only file I have written trying to push multiple objects to firebase. This is my first time using Firebase and Stormpath so any help would be greatly appreciated. Also one other thing that may be helpful is the error from the terminal being output when the issue happens:
POST /uploaded/-JapMLDYzPnbtjvt001X 200 690.689 ms - 2719
/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/firebase/lib/firebase-node.js:24
?a:null}function Db(a){try{a()}catch(b){setTimeout(function(){throw b;},Math.f
^
TypeError: Property 'next' of object #<IncomingMessage> is not a function
at fn (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:899:25)
at EventEmitter.app.render (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/application.js:532:5)
at ServerResponse.res.render (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:904:7)
at /Users/jpribesh/Desktop/Code/BanditSignBoss/routes/campaigns.js:20:25
at Array.forEach (native)
at /Users/jpribesh/Desktop/Code/BanditSignBoss/routes/campaigns.js:16:18
at /Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/firebase/lib/firebase-node.js:25:533
at Db (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/firebase/lib/firebase-node.js:24:165)
at Ye (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/firebase/lib/firebase-node.js:124:216)
at Ze (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/firebase/lib/firebase-node.js:123:818)
UPDATE: It seems that the connection errors are inconsistent. Sometimes the images display just fine, sometimes only some of the images get a connection error, and other times everything including the google map script gets a connection error. This is really throwing me off no idea what the issue is. Any help or suggestions is greatly appreciated!
UPDATE 2: I changed the function saving the image data to firebase to use the firebase push function callback (to indicate completion) and added a length check on the forEach loop running to save each image's data. See updated code above. I am now getting the following error for each image that is uploaded in the terminal, but the connection errors are gone:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:689:11)
at ServerResponse.header (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:666:10)
at ServerResponse.send (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:146:12)
at fn (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:900:10)
at View.exports.renderFile [as engine] (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/jade/lib/jade.js:325:12)
at View.render (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/view.js:93:8)
at EventEmitter.app.render (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/application.js:530:10)
at ServerResponse.res.render (/Users/jpribesh/Desktop/Code/BanditSignBoss/node_modules/express/lib/response.js:904:7)
at /Users/jpribesh/Desktop/Code/BanditSignBoss/routes/campaigns.js:20:25
at Array.forEach (native)
OK I finally figured out the issue here. I did a few things to remedy my problem. First I converted the route to use next properly to separate out each part of the route out, it processes the images, then saves, then renders. Here is the updated code from that file:
var express = require('express');
var router = express.Router();
var util = require('util');
var fs = require('fs');
var im = require('imagemagick');
var stormpath = require('express-stormpath');
var _ = require('lodash')
var Firebase = require('firebase');
function processData(req, res, next) {
function gatherImages(files, callback) {
//accept single image upload
if (!_.isArray(files)) {
files = [files];
}
var uploads = [];
var count = 0;
files.forEach(function(file) {
fs.exists(file.path, function(exists) {
if (exists) {
var name = req.body[file.originalname];
console.log(name);
var path = file.path;
var upFile = file.name;
uploads.push({
file: upFile,
imgPath: path,
caption: name || 'no comment'
});
count++;
}
if (files.length === count) {
callback(uploads);
}
});
});
}
function getGeoLoc(path, callback) {
im.readMetadata('./' + path, function(error, metadata) {
var geoCoords = false;
if (error) throw error;
if (metadata.exif.gpsLatitude && metadata.exif.gpsLatitudeRef) {
var lat = getDegrees(metadata.exif.gpsLatitude.split(','));
var latRef = metadata.exif.gpsLatitudeRef;
if (latRef === 'S') {
lat = lat * -1;
}
var lng = getDegrees(metadata.exif.gpsLongitude.split(','));
var lngRef = metadata.exif.gpsLongitudeRef;
if (lngRef === 'W') {
lng = lng * -1;
}
var coordinate = {
lat: lat,
lng: lng
};
geoCoords = coordinate.lat + ' ' + coordinate.lng;
console.log(geoCoords);
}
callback(geoCoords);
});
}
function getDegrees(lat) {
var degrees = 0;
for (var i = 0; i < lat.length; i++) {
var cleanNum = lat[i].replace(' ', '');
var parts = cleanNum.split('/');
var coord = parseInt(parts[0]) / parseInt(parts[1]);
if (i == 1) {
coord = coord / 60;
} else if (i == 2) {
coord = coord / 3600;
}
degrees += coord;
}
return degrees.toFixed(6);
}
function processImages(uploads, callback) {
var finalImages = [];
var count = 0;
uploads.forEach(function(upload) {
var path = upload.imgPath;
getGeoLoc(path, function(geoCoords) {
upload.coords = geoCoords;
finalImages.push(upload);
count++;
if (uploads.length === count) {
callback(finalImages);
}
});
});
}
if (req.files) {
if (req.files.size === 0) {
return next(new Error("Why didn't you select a file?"));
}
gatherImages(req.files.imageFiles, function(uploads) {
processImages(uploads, function(finalImages) {
req.finalImages = finalImages;
req.campaignId = req.param('campaignId');
next();
});
});
}
}
function saveImageInfo(req, res, next) {
var user = res.locals.user;
var count = 0;
var campaignPhotosRef = new Firebase('https://vivid-fire-567.firebaseio.com/BSB/userStore/' + user.username + '/campaigns/' + req.campaignId + '/photos');
var finalImages = req.finalImages;
finalImages.forEach(function(image) {
campaignPhotosRef.push(image, function(err) {
if (err) {
console.log(err);
} else {
console.log('Data saved successfully: ' + image);
count++;
if (req.finalImages.length === count) {
next();
}
}
});
});
}
router.post("/:campaignId", stormpath.loginRequired, processData, saveImageInfo, function(req, res) {
res.render("uploadMapPage", {
title: "File(s) Uploaded Successfully!",
files: req.finalImages,
campaignId: req.campaignId,
scripts: ['https://maps.googleapis.com/maps/api/js?key=AIzaSyCU42Wpv6BtNO51t7xGJYnatuPqgwnwk7c', '/javascripts/getPoints.js']
});
});
module.exports = router;
Then I realized in the tracestack I included in my question part of it was tracing back to another file I was using firebase in. I was using a call to .on() instead of using .once() when pulling my data. After reorganizing my route and changing all my calls to .on to .once for firebase data everything is now working properly. I think the real issue here was the use of .on() on my firebase calls instead of .once() as the .on() watches for events continually rather than .once which obviously only watches for it once.

How do I code a node.js proxy to use NTLMv2 authentication

I've tried to search through stackoverflow for a similar question but most people are asking about the client-side of the NTLMv2 protocol.
I'm implementing a proxy that is performing the server-side of the protocol to authenticate users connecting to the proxy.
I've coded a lot of the protocol but I'm now stuck because the documentation that should take me further is difficult to understand.
This is the best documentation I've found so far: http://www.innovation.ch/personal/ronald/ntlm.html, but how to deal with the LM and NT responses is oblivious to me.
The proxy is located on an application server. The domain server is a different machine.
Example code for the node proxy:
var http = require('http')
, request = require('request')
, ProxyAuth = require('./proxyAuth');
function handlerProxy(req, res) {
ProxyAuth.authorize(req, res);
var options = {
url: req.url,
method: req.method,
headers: req.headers
}
req.pipe(request(options)).pipe(res)
}
var server = http.createServer(handlerProxy);
server.listen(3000, function(){
console.log('Express server listening on port ' + 3000);
});
ProxyAuth.js code:
ProxyAuth = {
parseType3Msg: function(buf) {
var lmlen = buf.readUInt16LE(12);
var lmoff = buf.readUInt16LE(16);
var ntlen = buf.readUInt16LE(20);
var ntoff = buf.readUInt16LE(24);
var dlen = buf.readUInt16LE(28);
var doff = buf.readUInt16LE(32);
var ulen = buf.readUInt16LE(36);
var uoff = buf.readUInt16LE(40);
var hlen = buf.readUInt16LE(44);
var hoff = buf.readUInt16LE(48);
var domain = buf.slice(doff, doff+dlen).toString('utf8');
var user = buf.slice(uoff, uoff+ulen).toString('utf8');
var host = buf.slice(hoff, hoff+hlen).toString('utf8');
var lmresp = buf.slice(lmoff, lmoff+lmlen).toString('utf8');
var ntresp = buf.slice(ntoff, ntoff+ntlen).toString('utf8');
console.log(user, lmresp, ntresp);
/* NOW WHAT DO I DO? */
},
authorize: function(req, res) {
var auth = req.headers['authorization'];
if (!auth) {
res.writeHead(401, {
'WWW-Authenticate': 'NTLM',
});
res.end('<html><body>Proxy Authentication Required</body></html>');
}
else if(auth) {
var header = auth.split(' ');
var buf = new Buffer(header[1], 'base64');
var msg = buf.toString('utf8');
console.log("Decoded", msg);
if (header[0] == "NTLM") {
if (msg.substring(0,8) != "NTLMSSP\x00") {
res.writeHead(401, {
'WWW-Authenticate': 'NTLM',
});
res.end('<html><body>Header not recognized</body></html>');
}
// Type 1 message
if (msg[8] == "\x01") {
console.log(buf.toString('hex'));
var challenge = require('crypto').randomBytes(8);
var type2msg = "NTLMSSP\x00"+
"\x02\x00\x00\x00"+ // 8 message type
"\x00\x00\x00\x00"+ // 12 target name len/alloc
"\x00\x00\x00\x00"+ // 16 target name offset
"\x01\x82\x00\x00"+ // 20 flags
challenge.toString('utf8')+ // 24 challenge
"\x00\x00\x00\x00\x00\x00\x00\x00"+ // 32 context
"\x00\x00\x00\x00\x00\x00\x00\x00"; // 40 target info len/alloc/offset
type2msg = new Buffer(type2msg).toString('base64');
res.writeHead(401, {
'WWW-Authenticate': 'NTLM '+type2msg.trim(),
});
res.end();
}
else if (msg[8] == "\x03") {
console.log(buf.toString('hex'));
ProxyAuth.parseType3Msg(buf);
/* NOW WHAT DO I DO? */
}
}
else if (header[0] == "Basic") {
}
}
}
};
module.exports = ProxyAuth;
The /* NOW WHAT DO I DO? */ comment specifies where I am stuck.
I hope I put enough information there, but let me know if anything else is needed.

Node.js is unable to handle multiple tcp messages

Here is a simple TCP-Server stress test. As long as we send only one message per client everything works as expected. But when two messages per client are send,
the server suddenly stops without an exception or error.
So is this a bug or a feature?
var net = require("net");
var async = require("async");
var cluster = require("cluster");
// `ulimit -n` tells us that we can open max. 1024 files per process.
// Creating a socket means opening a file so we are limited.
var CLIENTS = 1000;
// Here is the weird part:
// - sending one message per client works fine
// - sending multiple message per client sucks
var MESSAGES = 2;
var TOTAL = CLIENTS * MESSAGES;
var PORT = 1234;
var HOST = "127.0.0.1";
if (cluster.isMaster) {
var count = 0;
var start = new Date;
var server = net.createServer(function(socket) {
socket.on("data", function(data) {
var t;
count++;
console.log("server received " + count + " messages");
socket.write(data, function(err) { if (err) console.error(err); });
if (count === TOTAL) {
t = (new Date) - start;
console.log("server received and sent " + count + " messages within " + t + "ms");
}
});
});
server.listen(PORT, HOST, function() { cluster.fork(); });
} else {
var run = function(i) {
var c = net.connect({ port: PORT, host: HOST }, function() {
var tasks = (function() {
var results = [];
for (var x = 1; x <= MESSAGES; ++x) {
results.push((function(x) {
return function(next) { c.write("Hello server!", next); };
})(x));
}
return results;
})();
async.series(tasks, function(err) {
if (err) { console.error(err); }
});
});
};
for (var i = 1; i <= CLIENTS; ++i) { run(i); }
}
Tested on Linux 3.11, Node.js 0.10.21
You're assuming that calling .write twice from a client triggers the data event twice on the server, not taking into account any buffering that might be going on which will coalecse multiple writes.
When the callback to .write is called, it doesn't mean the message it actually sent, it means that the message is put in some kernel buffer (which might contain more than one message when it's sent to the server).

Categories