Skip to content

Commit 33b4bbf

Browse files
author
greguz
committed
Initial commit
0 parents  commit 33b4bbf

7 files changed

Lines changed: 351 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.idea
3+
dump

dumper.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
var socket = require('./libs/socket')
2+
, path = require('path')
3+
, fs = require('fs');
4+
5+
var folder = path.join(process.argv[2] || __dirname, 'dump');
6+
7+
socket.on('error', function(err) {
8+
console.log('ERROR', err);
9+
});
10+
11+
socket.on('message', function(msg) {
12+
var id = new Date().getTime()
13+
, file = path.join(folder, id + '.readynas');
14+
15+
console.log('Writing ' + file + '...');
16+
17+
fs.writeFile(file, msg, function(err) {
18+
if (err) console.log('ERROR', err);
19+
else console.log('OK');
20+
});
21+
});
22+
23+
console.log('Creating folder ' + folder + '...');
24+
25+
fs.mkdir(folder, function(err) {
26+
if (err)
27+
console.log('ERROR', err);
28+
else
29+
socket.sendMagic();
30+
});
31+
32+
setTimeout(function() {
33+
console.log('END');
34+
process.exit();
35+
}, 10000);

index.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// #########################################################################
2+
// dependencies
3+
// #########################################################################
4+
5+
var socket = require('./libs/socket')
6+
, ReadyNAS = require('./libs/readynas')
7+
, _ = require('lodash');
8+
9+
10+
11+
// #########################################################################
12+
// module vars
13+
// #########################################################################
14+
15+
var _events = {};
16+
17+
18+
19+
// #########################################################################
20+
// utility functions
21+
// #########################################################################
22+
23+
var notifyEvent = function() {
24+
var args = _.values(arguments)
25+
, event = args.shift()
26+
, callback = _events[event];
27+
28+
if (typeof callback !== 'function') return;
29+
30+
callback.apply(this, args);
31+
};
32+
33+
34+
35+
// #########################################################################
36+
// socket settings
37+
// #########################################################################
38+
39+
socket.on('error', function(err) {
40+
notifyEvent('error', err);
41+
});
42+
43+
socket.on('message', function(msg) {
44+
try {
45+
var device = new ReadyNAS(msg);
46+
47+
notifyEvent('device', device);
48+
notifyEvent(device.ip, device);
49+
notifyEvent(device.hostname, device);
50+
notifyEvent(device.mac, device);
51+
} catch(e) {
52+
notifyEvent('error', e);
53+
}
54+
});
55+
56+
socket.open();
57+
58+
59+
60+
// #########################################################################
61+
// functions
62+
// #########################################################################
63+
64+
module.exports.options = function(options) {
65+
socket.close();
66+
socket.open(options);
67+
};
68+
69+
module.exports.sendMagic = function(options, callback) {
70+
socket.sendMagic();
71+
};
72+
73+
module.exports.on = function(event, callback) {
74+
_events[event] = callback;
75+
};

libs/readynas.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// #########################################################################
2+
// class definition
3+
// #########################################################################
4+
5+
var ReadyNAS = function(buffer) {
6+
if (!buffer instanceof Buffer) throw new Error('RAIDar buffer message required!');
7+
8+
this.buffer = buffer;
9+
this.message = buffer.toString('utf8');
10+
11+
this.header = null;
12+
13+
this.mac = null;
14+
this.hostname = null;
15+
this.ip = null;
16+
17+
this.info = {};
18+
19+
this.initInfo();
20+
21+
return this;
22+
};
23+
24+
25+
26+
// #########################################################################
27+
// private
28+
// #########################################################################
29+
30+
ReadyNAS.prototype.initInfo = function() {
31+
this.initHeaderInfo();
32+
this.initBodyInfo();
33+
this.initFooterInfo();
34+
};
35+
36+
ReadyNAS.prototype.initHeaderInfo = function() {
37+
this.header = this.message.substr(0, 28);
38+
39+
var self = this
40+
, firstLine = this.message.substring(28, this.message.indexOf('\n'))
41+
, firstInfo = firstLine.split('\t')
42+
, otherInfo = firstInfo.slice(3);
43+
44+
this.mac = firstInfo[0];
45+
this.hostname = firstInfo[1];
46+
this.ip = firstInfo[2];
47+
48+
otherInfo.forEach(function(info) {
49+
self.parseInfo(info);
50+
});
51+
};
52+
53+
ReadyNAS.prototype.initBodyInfo = function() {
54+
var self = this
55+
, lines = this.message.split('\n').slice(1);
56+
57+
lines.forEach(function(line) {
58+
if (line[0] === '\t') return;
59+
self.parseInfo(line);
60+
});
61+
};
62+
63+
ReadyNAS.prototype.initFooterInfo = function() {
64+
65+
// TODO write footer data initialization
66+
67+
};
68+
69+
ReadyNAS.prototype.parseInfo = function(str) {
70+
var arr = str.split('!!')
71+
, name = arr[0]
72+
, info = { _info : arr[1] };
73+
74+
if (!this.info[name]) this.info[name] = [];
75+
if (!arr[2]) return this.info[name].push(info);
76+
77+
var otherInfo = arr[2].split('::');
78+
79+
otherInfo.forEach(function(str) {
80+
var arr = str.split('=')
81+
, field = arr[0]
82+
, value = arr[1];
83+
84+
if (value) {
85+
info[field] = value;
86+
} else {
87+
info['_status'] = field;
88+
}
89+
});
90+
91+
return this.info[name].push(info);
92+
};
93+
94+
95+
96+
// #########################################################################
97+
// public
98+
// #########################################################################
99+
100+
ReadyNAS.prototype.toJSON = function(string) {
101+
var res = {
102+
message : this.message,
103+
mac : this.mac,
104+
hostname : this.hostname,
105+
ip : this.ip,
106+
info : this.info
107+
};
108+
109+
return string === true ? JSON.stringify(res) : res;
110+
};
111+
112+
113+
114+
// #########################################################################
115+
// export
116+
// #########################################################################
117+
118+
module.exports = ReadyNAS;

libs/socket.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// #########################################################################
2+
// dependencies
3+
// #########################################################################
4+
5+
var dgram = require('dgram')
6+
, _ = require('lodash');
7+
8+
9+
10+
// #########################################################################
11+
// module vars
12+
// #########################################################################
13+
14+
var exports = {}
15+
, _options = null
16+
, _socket = null
17+
, _events = {};
18+
19+
var _defaultOptions = {
20+
socketType : 'udp4',
21+
portToListen : 57877,
22+
targetHost : '255.255.255.255',
23+
targetPort : 22081,
24+
magicPacket : new Buffer('0000073e0000000100000000f8d496c3ffffffff0000001c00000000', 'hex')
25+
};
26+
27+
28+
29+
// #########################################################################
30+
// utility functions
31+
// #########################################################################
32+
33+
var notifyEvent = function() {
34+
var args = _.values(arguments)
35+
, event = args.shift()
36+
, callback = _events[event];
37+
38+
if (typeof callback !== 'function') return;
39+
40+
callback.apply(this, args);
41+
};
42+
43+
var socketError = function(err) {
44+
notifyEvent('error', err);
45+
};
46+
47+
var socketMessage = function(msg) {
48+
notifyEvent('message', msg);
49+
};
50+
51+
52+
53+
// #########################################################################
54+
// exports
55+
// #########################################################################
56+
57+
exports.open = function(options) {
58+
_options = _.extend(_.clone(_defaultOptions), options);
59+
60+
_socket = dgram.createSocket(_options.socketType);
61+
62+
_socket.on('error', socketError);
63+
_socket.on('message', socketMessage);
64+
65+
_socket.bind(_options.portToListen, function() {
66+
_socket.setBroadcast(true);
67+
});
68+
};
69+
70+
exports.close = function() {
71+
if (_socket) _socket.close();
72+
_socket = null;
73+
};
74+
75+
exports.on = function(event, callback) {
76+
_events[event] = callback;
77+
};
78+
79+
exports.sendMagic = function() {
80+
if (!_socket) exports.open();
81+
82+
_socket.send(_options.magicPacket, 0, _options.magicPacket.length, _options.targetPort, _options.targetHost, function(err) {
83+
if (err) notifyEvent('error', err);
84+
});
85+
};
86+
87+
module.exports = exports;

package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "raidar",
3+
"version": "0.1.0",
4+
"description": "NetGear RAIDar node.js implementation",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "node test.js",
8+
"dump": "node dumper.js $1"
9+
},
10+
"author": "Gregoletto Giacomo",
11+
"license": "MIT",
12+
"dependencies": {
13+
"lodash": "^3.4.0"
14+
}
15+
}

test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
var raidar = require('./index');
2+
3+
console.log('Testing for 10 seconds...');
4+
5+
raidar.on('error', function(err) {
6+
console.log('ERROR', err);
7+
});
8+
9+
raidar.on('device', function(device) {
10+
console.log('Response from ' + device.ip + ' - ' + device.hostname + ' (' + device.mac + ')');
11+
});
12+
13+
raidar.sendMagic();
14+
15+
setTimeout(function() {
16+
console.log('END');
17+
process.exit();
18+
}, 10000);

0 commit comments

Comments
 (0)