Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
var b = require('bonescript');
var util = require('util');
var fs = require('fs');
var configFile = '/etc/default/bonescript';
var server;
//read the configuration from configFile
fs.readFile(configFile, {
encoding: 'ascii'
}, function read(err, data) {
if (err) {
server = b.serverStart(); //start server with default settings
} else {
data = JSON.parse(data); //start server with saved config
server = b.serverStart(data.port, data.directory, {
data: data.passphrase,
hash: data.hash
});
}
onServerStart();
});

var server = b.serverStart();

server.on('server$listening', serverListening);
server.on('server$error', serverError);
server.on('server$connection', serverConnection);
function onServerStart() {
server.on('server$listening', serverListening);
server.on('server$error', serverError);
server.on('server$connection', serverConnection);
}

function serverListening() {
if (debug) winston.debug('Server listening');
Expand Down
20 changes: 15 additions & 5 deletions src/bonescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ _bonescript.on.connect = function () {};
_bonescript.on.connecting = function () {};
_bonescript.on.disconnect = function () {};
_bonescript.on.connect_failed = function () {};
_bonescript.on.error = function () {};
_bonescript.on.error = function (err) {
throw (new Error(err))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This runs asynchronously on load when loaded by a browser? How do we catch this error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not very sure how we will be able to catch this error from the browser , however if the current implementation is used, then a 401 Unauthorized response could be sent for unauthorized sessions from browser.

};
_bonescript.on.reconnect = function () {};
_bonescript.on.reconnect_failed = function () {};
_bonescript.on.reconnecting = function () {};
Expand All @@ -16,9 +18,13 @@ _bonescript.on.initialized = function () {};
(function () {
if (typeof document == 'undefined') {
var io = require('socket.io-client');
module.exports.startClient = function (host, port, callback) {
var crypto = require('crypto');
module.exports.startClient = function (host, callback) {
var passphrase_hash;
if (host.password)
passphrase_hash = crypto.createHash('sha256').update(host.password).digest("hex"); //generate sha256 hash for supplied password
_bonescript.on.initialized = callback;
var socket = _onSocketIOLoaded(host, port, io);
var socket = _onSocketIOLoaded(host.address, host.port, io, passphrase_hash);
}
return;
}
Expand All @@ -32,14 +38,18 @@ _bonescript.on.initialized = function () {};
scriptObj.onload = _onSocketIOLoaded;
}());

function _onSocketIOLoaded(host, port, socketio) {
function _onSocketIOLoaded(host, port, socketio, passphrase_hash) {
//console.log("socket.io loaded");
if (typeof host == 'undefined') host = '___INSERT_HOST___';
if (typeof port == 'undefined') port = 80;
if (typeof socketio == 'undefined' && typeof io != 'undefined') socketio = io;
var socket;
if (typeof host == 'string')
socket = socketio('http://' + host + ':' + port);
socket = socketio('http://' + host + ':' + port, {
extraHeaders: {
'Authorization': typeof passphrase_hash != 'undefined' ? passphrase_hash : null //send passphrase_has as Authorization extraheader
}
});
else
socket = socketio('___INSERT_HOST___', {
port: port
Expand Down
10 changes: 5 additions & 5 deletions src/ffiimp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var my = require('./my');
var ffi = my.require('ffi');

var debug = process.env.DEBUG ? true : false;

//function to convert bonescript pin identifier to MRAA's format
var mraaGPIO = function (pin) {
var pinObject = bone.getPinObject(pin);
var pinNo;
Expand All @@ -21,7 +21,7 @@ var mraaGPIO = function (pin) {
}
return '0x' + pinNo.toString(16);
};

// function to write a .c file at path , similar to writeTextFile
var writeCModule = function (filename, data, callback) {
if (filename.indexOf(".c") == -1)
filename += ".c";
Expand All @@ -41,12 +41,12 @@ var writeCModule = function (filename, data, callback) {
}
}
};

//load C module from shared object at path
var loadCModule = function (path, args, mraa) {
//compile at the path if shared object does not exist
//compile at the path if shared object does not exist
if (path.indexOf('.c') != -1)
path = path.replace('.c', '');
mraa = mraa || false; // link mraa
mraa = mraa || false; // link mraa
var inPath = path + '.c';
var shellCmd = 'gcc -shared -fpic ' + inPath + ' -o ' + path + '.so';
if (mraa) shellCmd += ' -lmraa';
Expand Down
17 changes: 11 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ f.pinMode = function (pin, direction, mux, pullup, slew, callback) {
) {
var err = 'pinMode only supports ANALOG_OUTPUT for PWM pins: ' + pin.key;
winston.info(err);
if (callback) {
if (callback) { //support both nodestyle and oldstyle callbacks based on arguments length
if (callback.length == 1) {
winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)");
callback({
Expand Down Expand Up @@ -265,7 +265,7 @@ f.digitalWrite = function (pin, value, callback) {
var gpioEnabled = (7 == f.getPinMode(pin).mux); //check whether pin set as gpio
if (!gpioEnabled) {
winston.debug([pin.key, value] + ' set as ANALOG_OUTPUT modifying duty cycle according to value');
f.analogWrite(pin, value, myCallback); //write duty cycle as per value
f.analogWrite(pin, value, 2000, myCallback); //write duty cycle as per value
return (true);
}
}
Expand Down Expand Up @@ -558,14 +558,19 @@ f.analogWrite = function (pin, value, freq, callback) {

// Make sure the pin has a PWM associated
if (typeof pin.pwm == 'undefined') {
//handle analogWrite() on digital OUTPUT
if (typeof pin.gpio != 'undefined') {
if (value >= 0.5) {
resp = f.digitalWrite(pin, g.HIGH, callback);
if (callback) callback(resp);
if (callback)
f.digitalWrite(pin, g.HIGH, callback);
else
f.digitalWrite(pin, g.HIGH);
return (true);
} else {
resp = f.digitalWrite(pin, g.LOW, callback);
if (callback) callback(resp);
if (callback)
f.digitalWrite(pin, g.LOW, callback);
else
f.digitalWrite(pin, g.LOW);
return (true);
}
}
Expand Down
21 changes: 16 additions & 5 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var http = require('http');
var winston = require('winston');
var express = require('express');
var events = require('events');
var crypto = require('crypto');
var socketHandlers = require('./socket_handlers');

var serverEmitter = new events.EventEmitter();
Expand All @@ -16,14 +17,21 @@ myrequire('systemd', function () {
if (debug) winston.debug("Startup as socket-activated service under systemd not enabled");
});

var serverStart = function (port, directory, callback) {
var serverStart = function (port, directory, passphrase, callback) {
if (port === undefined) {
port = (process.env.LISTEN_PID > 0) ? 'systemd' : ((process.env.PORT) ? process.env.PORT : 80);
}
if (directory === undefined) {
directory = (process.env.SERVER_DIR) ? process.env.SERVER_DIR : '/usr/share/bone101';
}
var server = mylisten(port, directory);
var passphrase_hash;
if (passphrase) {
if (passphrase.hash) //whether passphrase supplied as hash/text
passphrase_hash = passphrase.data;
else
passphrase_hash = crypto.createHash('sha256').update(passphrase.data).digest("hex"); //generate hash
}
var server = mylisten(port, directory, passphrase_hash);
serverEmitter.on('newListner', addServerListener);

function addServerListener(event, listener) {
Expand All @@ -37,21 +45,24 @@ var serverStart = function (port, directory, callback) {
}

if (callback) {
callback(serverEmitter);
callback({
server: server,
serverEmitter: serverEmitter
});
}

return (serverEmitter);
};

function mylisten(port, directory) {
function mylisten(port, directory, passphrase_hash) {
winston.info("Opening port " + port + " to serve up " + directory);
var app = express();
app.get('/bonescript.js', socketHandlers.socketJSReqHandler);
app.use('/bone101', express.static(directory));
app.use('/bone101/static', express.static(directory + "/static"));
app.use(express.static(directory));
var server = http.createServer(app);
socketHandlers.addSocketListeners(server, serverEmitter);
socketHandlers.addSocketListeners(server, serverEmitter, passphrase_hash);
server.listen(port);
return (server);
}
Expand Down
26 changes: 21 additions & 5 deletions src/socket_handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ var url = require('url');
var child_process = require('child_process');
var winston = require('winston');
var socketio = require('socket.io');

var debug = process.env.DEBUG ? true : false;

var socketJSReqHandler = function (req, res) {
Expand All @@ -33,14 +32,32 @@ var socketJSReqHandler = function (req, res) {
}
}

var addSocketListeners = function (server, serverEmitter) {
var addSocketListeners = function (server, serverEmitter, passphrase_hash) {
var io = socketio(server);
if (passphrase_hash) { //attach middleware to handle authentication
io.use(function (socket, next) {
socket.auth = false; //consider the all sockets initially as unauthorized
if (socket.handshake.headers.authorization) {
if (socket.handshake.headers.authorization == passphrase_hash) {
socket.auth = true; //authorize the socket
next();
} else
next(new Error("Authentication Failed : incorrect passphrase !!"));
} else {
next(new Error("Authentication data not send !!"));
}
});
}
if (debug) winston.debug('Listening for new socket.io clients');
io.on('connection', onconnect);
io.on('connection', function (socket) {
if (socket.auth || !passphrase_hash)
onconnect(socket);
else
socket.disconnect('unauthorized');
});

function onconnect(socket) {
winston.debug('Client connected');

serverEmitter.emit('socket$connect', socket);

// on disconnect
Expand Down Expand Up @@ -139,7 +156,6 @@ var addSocketListeners = function (server, serverEmitter) {

return (io);
}

// most heavily borrowed from https://github.com/itchyny/browsershell
function spawn(socket) {
var stream = '';
Expand Down
39 changes: 39 additions & 0 deletions test/test-analogread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var b = require('bonescript');

var pinKeys = [];
for (var i = 1; i <= 36; i++) {
pinKeys.push("P1_" + i);
pinKeys.push("P2_" + i);
}
for (var i = 1; i <= 46; i++) {
pinKeys.push("P8_" + i);
pinKeys.push("P9_" + i);
}
exports.testanalogread1 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
var y = b.analogRead(pinKeys[x]);
test.ok(typeof y == 'number');
}
test.done();
}
exports.testanalogread2 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
b.analogRead(pinKeys[x], function (x) {
test.ok(typeof x.value == 'number' && !x.err);
});
if (x == pinKeys.length - 1)
test.done();
}
}
exports.testanalogread3 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
b.analogRead(pinKeys[x], function (err, value) {
test.ok(typeof value == 'number' && !err);
});
if (x == pinKeys.length - 1)
test.done();
}
}
30 changes: 30 additions & 0 deletions test/test-analogwrite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var b = require('bonescript');

var pinKeys = [];
for (var i = 1; i <= 36; i++) {
pinKeys.push("P1_" + i);
pinKeys.push("P2_" + i);
}
for (var i = 1; i <= 46; i++) {
pinKeys.push("P8_" + i);
pinKeys.push("P9_" + i);
}
exports.testanalogwrite1 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
test.doesNotThrow(function () {
b.analogWrite(pinKeys[x], Math.random());
});
}
test.done();
}
exports.testanalogwrite2 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
b.analogWrite(pinKeys[x], Math.random(), 2000, function (x) {
test.ok(true);
});
if (x == pinKeys.length - 1)
test.done();
}
}
39 changes: 39 additions & 0 deletions test/test-digitalread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var b = require('bonescript');

var pinKeys = [];
for (var i = 1; i <= 36; i++) {
pinKeys.push("P1_" + i);
pinKeys.push("P2_" + i);
}
for (var i = 1; i <= 46; i++) {
pinKeys.push("P8_" + i);
pinKeys.push("P9_" + i);
}
exports.testdigitalRead1 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
var y = b.digitalRead(pinKeys[x]);
test.ok(typeof y == 'number');
}
test.done();
}
exports.testdigitalRead2 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
b.digitalRead(pinKeys[x], function (x) {
test.ok(typeof x.value == 'number' && !x.err);
});
if (x == pinKeys.length - 1)
test.done();
}
}
exports.testdigitalRead3 = function (test) {
test.expect(pinKeys.length);
for (var x in pinKeys) {
b.digitalRead(pinKeys[x], function (err, value) {
test.ok(typeof value == 'number' && !err);
});
if (x == pinKeys.length - 1)
test.done();
}
}
Loading