@cryptotaxi247 / netdata-1 / commits / cac53fd15

added SNMP node.js data collector; node.d.plugin now supports multiple processors (http, snmp at the ones currently implemented)

Costa Tsaousis (ktsaou) committed Feb 5, 2016 at 02:02 UTC cac53fd155c250599871b12ebc1e7f83e1616777
14 files changed +2624 -104
LICENSE.md
+23
@@ -114,4 +114,27 @@ connectivity is not available.
114 Copyright 2015, Mike Bostock
115 [BSD License](http://opensource.org/licenses/BSD-3-Clause)
116
117 +
118 +- [node-extend](https://github.com/justmoon/node-extend)
119 +
120 + Copyright 2014, Stefan Thomas
121 + [MIT License](https://github.com/justmoon/node-extend/blob/master/LICENSE)
122 +
123 +
124 +- [node-net-snmp](https://github.com/stephenwvickers/node-net-snmp)
125 +
126 + Copyright 2013, Stephen Vickers
127 + [MIT License](https://github.com/stephenwvickers/node-net-snmp)
128 +
129
130 +- [node-asn1](https://github.com/mcavage/node-asn1)
131 +
132 + Copyright 2011, Mark Cavage
133 + [MIT License](https://github.com/mcavage/node-asn1)
134 +
135 +
136 +- [pixl-xml](https://github.com/jhuckaby/pixl-xml)
137 +
138 + Copyright 2015, Joseph Huckaby
139 + [MIT License](https://github.com/jhuckaby/pixl-xml)
140 +
node.d/Makefile.am
+12
@@ -4,6 +4,7 @@ dist_node_SCRIPTS = \
4 README.md \
5 named.node.js \
6 sma_webbox.node.js \
7 + snmp.node.js \
8 $(NULL)
9
10 nodemodulesdir=$(nodedir)/node_modules
@@ -11,4 +12,15 @@ dist_nodemodules_DATA = \
12 node_modules/netdata.js \
13 node_modules/extend.js \
14 node_modules/pixl-xml.js \
15 + node_modules/net-snmp.js \
16 + node_modules/asn1.js \
17 + $(NULL)
18 +
19 +nodemodulesberdir=$(nodedir)/node_modules/ber
20 +dist_nodemodulesber_DATA = \
21 + node_modules/ber/index.js \
22 + node_modules/ber/errors.js \
23 + node_modules/ber/reader.js \
24 + node_modules/ber/types.js \
25 + node_modules/ber/writer.js \
26 $(NULL)
node.d/named.node.js
+5 -7
@@ -46,7 +46,7 @@ if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plug
46 var named = {
47 name: __filename,
48 enable_autodetect: true,
49 - update_every: 1000,
49 + update_every: 1,
50
51 charts: {},
52
@@ -60,7 +60,7 @@ var named = {
60 category: category_prefix + '_' + service.name, // the category of the chart
61 type: type, // the type of the chart
62 priority: priority, // the priority relative to others in the same family and category
63 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
63 + update_every: service.update_every, // the expected update frequency of the chart
64 dimensions: {}
65 }
66
@@ -338,7 +338,7 @@ var named = {
338 category: 'named', // the category of the chart
339 type: netdata.chartTypes.line, // the type of the chart
340 priority: 150, // the priority relative to others in the same family and category
341 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
341 + update_every: service.update_every, // the expected update frequency of the chart
342 dimensions: {
343 'clients': {
344 id: 'clients', // the unique id of the dimension
@@ -442,7 +442,7 @@ var named = {
442 category: 'named', // the category of the chart
443 type: netdata.chartTypes.line, // the type of the chart
444 priority: 5000, // the priority relative to others in the same family and category
445 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
445 + update_every: service.update_every, // the expected update frequency of the chart
446 dimensions: {
447 'queries': {
448 id: 'queries', // the unique id of the dimension
@@ -486,7 +486,7 @@ var named = {
486 category: 'named', // the category of the chart
487 type: netdata.chartTypes.area, // the type of the chart
488 priority: 8000, // the priority relative to others in the same family and category
489 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
489 + update_every: service.update_every, // the expected update frequency of the chart
490 dimensions: {
491 'CacheHits': {
492 id: 'CacheHits', // the unique id of the dimension
@@ -563,8 +563,6 @@ var named = {
563 while(len--) {
564 if(typeof config.servers[len].update_every === 'undefined')
565 config.servers[len].update_every = this.update_every;
566 - else
567 - config.servers[len].update_every = config.servers[len].update_every * 1000;
566
567 this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every);
568 added++;
node.d/node_modules/asn1.js new
+20
@@ -0,0 +1,20 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +// If you have no idea what ASN.1 or BER is, see this:
4 +// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
5 +
6 +var Ber = require('./ber/index');
7 +
8 +
9 +
10 +///--- Exported API
11 +
12 +module.exports = {
13 +
14 + Ber: Ber,
15 +
16 + BerReader: Ber.Reader,
17 +
18 + BerWriter: Ber.Writer
19 +
20 +};
node.d/node_modules/ber/errors.js new
+13
@@ -0,0 +1,13 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +
4 +module.exports = {
5 +
6 + newInvalidAsn1Error: function(msg) {
7 + var e = new Error();
8 + e.name = 'InvalidAsn1Error';
9 + e.message = msg || '';
10 + return e;
11 + }
12 +
13 +};
node.d/node_modules/ber/index.js new
+27
@@ -0,0 +1,27 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +var errors = require('./errors');
4 +var types = require('./types');
5 +
6 +var Reader = require('./reader');
7 +var Writer = require('./writer');
8 +
9 +
10 +///--- Exports
11 +
12 +module.exports = {
13 +
14 + Reader: Reader,
15 +
16 + Writer: Writer
17 +
18 +};
19 +
20 +for (var t in types) {
21 + if (types.hasOwnProperty(t))
22 + module.exports[t] = types[t];
23 +}
24 +for (var e in errors) {
25 + if (errors.hasOwnProperty(e))
26 + module.exports[e] = errors[e];
27 +}
node.d/node_modules/ber/reader.js new
+261
@@ -0,0 +1,261 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +var assert = require('assert');
4 +
5 +var ASN1 = require('./types');
6 +var errors = require('./errors');
7 +
8 +
9 +///--- Globals
10 +
11 +var newInvalidAsn1Error = errors.newInvalidAsn1Error;
12 +
13 +
14 +
15 +///--- API
16 +
17 +function Reader(data) {
18 + if (!data || !Buffer.isBuffer(data))
19 + throw new TypeError('data must be a node Buffer');
20 +
21 + this._buf = data;
22 + this._size = data.length;
23 +
24 + // These hold the "current" state
25 + this._len = 0;
26 + this._offset = 0;
27 +}
28 +
29 +Object.defineProperty(Reader.prototype, 'length', {
30 + enumerable: true,
31 + get: function () { return (this._len); }
32 +});
33 +
34 +Object.defineProperty(Reader.prototype, 'offset', {
35 + enumerable: true,
36 + get: function () { return (this._offset); }
37 +});
38 +
39 +Object.defineProperty(Reader.prototype, 'remain', {
40 + get: function () { return (this._size - this._offset); }
41 +});
42 +
43 +Object.defineProperty(Reader.prototype, 'buffer', {
44 + get: function () { return (this._buf.slice(this._offset)); }
45 +});
46 +
47 +
48 +/**
49 + * Reads a single byte and advances offset; you can pass in `true` to make this
50 + * a "peek" operation (i.e., get the byte, but don't advance the offset).
51 + *
52 + * @param {Boolean} peek true means don't move offset.
53 + * @return {Number} the next byte, null if not enough data.
54 + */
55 +Reader.prototype.readByte = function(peek) {
56 + if (this._size - this._offset < 1)
57 + return null;
58 +
59 + var b = this._buf[this._offset] & 0xff;
60 +
61 + if (!peek)
62 + this._offset += 1;
63 +
64 + return b;
65 +};
66 +
67 +
68 +Reader.prototype.peek = function() {
69 + return this.readByte(true);
70 +};
71 +
72 +
73 +/**
74 + * Reads a (potentially) variable length off the BER buffer. This call is
75 + * not really meant to be called directly, as callers have to manipulate
76 + * the internal buffer afterwards.
77 + *
78 + * As a result of this call, you can call `Reader.length`, until the
79 + * next thing called that does a readLength.
80 + *
81 + * @return {Number} the amount of offset to advance the buffer.
82 + * @throws {InvalidAsn1Error} on bad ASN.1
83 + */
84 +Reader.prototype.readLength = function(offset) {
85 + if (offset === undefined)
86 + offset = this._offset;
87 +
88 + if (offset >= this._size)
89 + return null;
90 +
91 + var lenB = this._buf[offset++] & 0xff;
92 + if (lenB === null)
93 + return null;
94 +
95 + if ((lenB & 0x80) == 0x80) {
96 + lenB &= 0x7f;
97 +
98 + if (lenB == 0)
99 + throw newInvalidAsn1Error('Indefinite length not supported');
100 +
101 + if (lenB > 4)
102 + throw newInvalidAsn1Error('encoding too long');
103 +
104 + if (this._size - offset < lenB)
105 + return null;
106 +
107 + this._len = 0;
108 + for (var i = 0; i < lenB; i++)
109 + this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
110 +
111 + } else {
112 + // Wasn't a variable length
113 + this._len = lenB;
114 + }
115 +
116 + return offset;
117 +};
118 +
119 +
120 +/**
121 + * Parses the next sequence in this BER buffer.
122 + *
123 + * To get the length of the sequence, call `Reader.length`.
124 + *
125 + * @return {Number} the sequence's tag.
126 + */
127 +Reader.prototype.readSequence = function(tag) {
128 + var seq = this.peek();
129 + if (seq === null)
130 + return null;
131 + if (tag !== undefined && tag !== seq)
132 + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
133 + ': got 0x' + seq.toString(16));
134 +
135 + var o = this.readLength(this._offset + 1); // stored in `length`
136 + if (o === null)
137 + return null;
138 +
139 + this._offset = o;
140 + return seq;
141 +};
142 +
143 +
144 +Reader.prototype.readInt = function() {
145 + return this._readTag(ASN1.Integer);
146 +};
147 +
148 +
149 +Reader.prototype.readBoolean = function() {
150 + return (this._readTag(ASN1.Boolean) === 0 ? false : true);
151 +};
152 +
153 +
154 +Reader.prototype.readEnumeration = function() {
155 + return this._readTag(ASN1.Enumeration);
156 +};
157 +
158 +
159 +Reader.prototype.readString = function(tag, retbuf) {
160 + if (!tag)
161 + tag = ASN1.OctetString;
162 +
163 + var b = this.peek();
164 + if (b === null)
165 + return null;
166 +
167 + if (b !== tag)
168 + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
169 + ': got 0x' + b.toString(16));
170 +
171 + var o = this.readLength(this._offset + 1); // stored in `length`
172 +
173 + if (o === null)
174 + return null;
175 +
176 + if (this.length > this._size - o)
177 + return null;
178 +
179 + this._offset = o;
180 +
181 + if (this.length === 0)
182 + return retbuf ? new Buffer(0) : '';
183 +
184 + var str = this._buf.slice(this._offset, this._offset + this.length);
185 + this._offset += this.length;
186 +
187 + return retbuf ? str : str.toString('utf8');
188 +};
189 +
190 +Reader.prototype.readOID = function(tag) {
191 + if (!tag)
192 + tag = ASN1.OID;
193 +
194 + var b = this.readString(tag, true);
195 + if (b === null)
196 + return null;
197 +
198 + var values = [];
199 + var value = 0;
200 +
201 + for (var i = 0; i < b.length; i++) {
202 + var byte = b[i] & 0xff;
203 +
204 + value <<= 7;
205 + value += byte & 0x7f;
206 + if ((byte & 0x80) == 0) {
207 + values.push(value);
208 + value = 0;
209 + }
210 + }
211 +
212 + value = values.shift();
213 + values.unshift(value % 40);
214 + values.unshift((value / 40) >> 0);
215 +
216 + return values.join('.');
217 +};
218 +
219 +
220 +Reader.prototype._readTag = function(tag) {
221 + assert.ok(tag !== undefined);
222 +
223 + var b = this.peek();
224 +
225 + if (b === null)
226 + return null;
227 +
228 + if (b !== tag)
229 + throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
230 + ': got 0x' + b.toString(16));
231 +
232 + var o = this.readLength(this._offset + 1); // stored in `length`
233 + if (o === null)
234 + return null;
235 +
236 + if (this.length > 4)
237 + throw newInvalidAsn1Error('Integer too long: ' + this.length);
238 +
239 + if (this.length > this._size - o)
240 + return null;
241 + this._offset = o;
242 +
243 + var fb = this._buf[this._offset];
244 + var value = 0;
245 +
246 + for (var i = 0; i < this.length; i++) {
247 + value <<= 8;
248 + value |= (this._buf[this._offset++] & 0xff);
249 + }
250 +
251 + if ((fb & 0x80) == 0x80 && i !== 4)
252 + value -= (1 << (i * 8));
253 +
254 + return value >> 0;
255 +};
256 +
257 +
258 +
259 +///--- Exported API
260 +
261 +module.exports = Reader;
node.d/node_modules/ber/types.js new
+36
@@ -0,0 +1,36 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +
4 +module.exports = {
5 + EOC: 0,
6 + Boolean: 1,
7 + Integer: 2,
8 + BitString: 3,
9 + OctetString: 4,
10 + Null: 5,
11 + OID: 6,
12 + ObjectDescriptor: 7,
13 + External: 8,
14 + Real: 9, // float
15 + Enumeration: 10,
16 + PDV: 11,
17 + Utf8String: 12,
18 + RelativeOID: 13,
19 + Sequence: 16,
20 + Set: 17,
21 + NumericString: 18,
22 + PrintableString: 19,
23 + T61String: 20,
24 + VideotexString: 21,
25 + IA5String: 22,
26 + UTCTime: 23,
27 + GeneralizedTime: 24,
28 + GraphicString: 25,
29 + VisibleString: 26,
30 + GeneralString: 28,
31 + UniversalString: 29,
32 + CharacterString: 30,
33 + BMPString: 31,
34 + Constructor: 32,
35 + Context: 128
36 +};
node.d/node_modules/ber/writer.js new
+316
@@ -0,0 +1,316 @@
1 +// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
2 +
3 +var assert = require('assert');
4 +var ASN1 = require('./types');
5 +var errors = require('./errors');
6 +
7 +
8 +///--- Globals
9 +
10 +var newInvalidAsn1Error = errors.newInvalidAsn1Error;
11 +
12 +var DEFAULT_OPTS = {
13 + size: 1024,
14 + growthFactor: 8
15 +};
16 +
17 +
18 +///--- Helpers
19 +
20 +function merge(from, to) {
21 + assert.ok(from);
22 + assert.equal(typeof(from), 'object');
23 + assert.ok(to);
24 + assert.equal(typeof(to), 'object');
25 +
26 + var keys = Object.getOwnPropertyNames(from);
27 + keys.forEach(function(key) {
28 + if (to[key])
29 + return;
30 +
31 + var value = Object.getOwnPropertyDescriptor(from, key);
32 + Object.defineProperty(to, key, value);
33 + });
34 +
35 + return to;
36 +}
37 +
38 +
39 +
40 +///--- API
41 +
42 +function Writer(options) {
43 + options = merge(DEFAULT_OPTS, options || {});
44 +
45 + this._buf = new Buffer(options.size || 1024);
46 + this._size = this._buf.length;
47 + this._offset = 0;
48 + this._options = options;
49 +
50 + // A list of offsets in the buffer where we need to insert
51 + // sequence tag/len pairs.
52 + this._seq = [];
53 +}
54 +
55 +Object.defineProperty(Writer.prototype, 'buffer', {
56 + get: function () {
57 + if (this._seq.length)
58 + throw new InvalidAsn1Error(this._seq.length + ' unended sequence(s)');
59 +
60 + return (this._buf.slice(0, this._offset));
61 + }
62 +});
63 +
64 +Writer.prototype.writeByte = function(b) {
65 + if (typeof(b) !== 'number')
66 + throw new TypeError('argument must be a Number');
67 +
68 + this._ensure(1);
69 + this._buf[this._offset++] = b;
70 +};
71 +
72 +
73 +Writer.prototype.writeInt = function(i, tag) {
74 + if (typeof(i) !== 'number')
75 + throw new TypeError('argument must be a Number');
76 + if (typeof(tag) !== 'number')
77 + tag = ASN1.Integer;
78 +
79 + var sz = 4;
80 +
81 + while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) &&
82 + (sz > 1)) {
83 + sz--;
84 + i <<= 8;
85 + }
86 +
87 + if (sz > 4)
88 + throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff');
89 +
90 + this._ensure(2 + sz);
91 + this._buf[this._offset++] = tag;
92 + this._buf[this._offset++] = sz;
93 +
94 + while (sz-- > 0) {
95 + this._buf[this._offset++] = ((i & 0xff000000) >>> 24);
96 + i <<= 8;
97 + }
98 +
99 +};
100 +
101 +
102 +Writer.prototype.writeNull = function() {
103 + this.writeByte(ASN1.Null);
104 + this.writeByte(0x00);
105 +};
106 +
107 +
108 +Writer.prototype.writeEnumeration = function(i, tag) {
109 + if (typeof(i) !== 'number')
110 + throw new TypeError('argument must be a Number');
111 + if (typeof(tag) !== 'number')
112 + tag = ASN1.Enumeration;
113 +
114 + return this.writeInt(i, tag);
115 +};
116 +
117 +
118 +Writer.prototype.writeBoolean = function(b, tag) {
119 + if (typeof(b) !== 'boolean')
120 + throw new TypeError('argument must be a Boolean');
121 + if (typeof(tag) !== 'number')
122 + tag = ASN1.Boolean;
123 +
124 + this._ensure(3);
125 + this._buf[this._offset++] = tag;
126 + this._buf[this._offset++] = 0x01;
127 + this._buf[this._offset++] = b ? 0xff : 0x00;
128 +};
129 +
130 +
131 +Writer.prototype.writeString = function(s, tag) {
132 + if (typeof(s) !== 'string')
133 + throw new TypeError('argument must be a string (was: ' + typeof(s) + ')');
134 + if (typeof(tag) !== 'number')
135 + tag = ASN1.OctetString;
136 +
137 + var len = Buffer.byteLength(s);
138 + this.writeByte(tag);
139 + this.writeLength(len);
140 + if (len) {
141 + this._ensure(len);
142 + this._buf.write(s, this._offset);
143 + this._offset += len;
144 + }
145 +};
146 +
147 +
148 +Writer.prototype.writeBuffer = function(buf, tag) {
149 + if (typeof(tag) !== 'number')
150 + throw new TypeError('tag must be a number');
151 + if (!Buffer.isBuffer(buf))
152 + throw new TypeError('argument must be a buffer');
153 +
154 + this.writeByte(tag);
155 + this.writeLength(buf.length);
156 + this._ensure(buf.length);
157 + buf.copy(this._buf, this._offset, 0, buf.length);
158 + this._offset += buf.length;
159 +};
160 +
161 +
162 +Writer.prototype.writeStringArray = function(strings) {
163 + if ((!strings instanceof Array))
164 + throw new TypeError('argument must be an Array[String]');
165 +
166 + var self = this;
167 + strings.forEach(function(s) {
168 + self.writeString(s);
169 + });
170 +};
171 +
172 +// This is really to solve DER cases, but whatever for now
173 +Writer.prototype.writeOID = function(s, tag) {
174 + if (typeof(s) !== 'string')
175 + throw new TypeError('argument must be a string');
176 + if (typeof(tag) !== 'number')
177 + tag = ASN1.OID;
178 +
179 + if (!/^([0-9]+\.){3,}[0-9]+$/.test(s))
180 + throw new Error('argument is not a valid OID string');
181 +
182 + function encodeOctet(bytes, octet) {
183 + if (octet < 128) {
184 + bytes.push(octet);
185 + } else if (octet < 16384) {
186 + bytes.push((octet >>> 7) | 0x80);
187 + bytes.push(octet & 0x7F);
188 + } else if (octet < 2097152) {
189 + bytes.push((octet >>> 14) | 0x80);
190 + bytes.push(((octet >>> 7) | 0x80) & 0xFF);
191 + bytes.push(octet & 0x7F);
192 + } else if (octet < 268435456) {
193 + bytes.push((octet >>> 21) | 0x80);
194 + bytes.push(((octet >>> 14) | 0x80) & 0xFF);
195 + bytes.push(((octet >>> 7) | 0x80) & 0xFF);
196 + bytes.push(octet & 0x7F);
197 + } else {
198 + bytes.push(((octet >>> 28) | 0x80) & 0xFF);
199 + bytes.push(((octet >>> 21) | 0x80) & 0xFF);
200 + bytes.push(((octet >>> 14) | 0x80) & 0xFF);
201 + bytes.push(((octet >>> 7) | 0x80) & 0xFF);
202 + bytes.push(octet & 0x7F);
203 + }
204 + }
205 +
206 + var tmp = s.split('.');
207 + var bytes = [];
208 + bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10));
209 + tmp.slice(2).forEach(function(b) {
210 + encodeOctet(bytes, parseInt(b, 10));
211 + });
212 +
213 + var self = this;
214 + this._ensure(2 + bytes.length);
215 + this.writeByte(tag);
216 + this.writeLength(bytes.length);
217 + bytes.forEach(function(b) {
218 + self.writeByte(b);
219 + });
220 +};
221 +
222 +
223 +Writer.prototype.writeLength = function(len) {
224 + if (typeof(len) !== 'number')
225 + throw new TypeError('argument must be a Number');
226 +
227 + this._ensure(4);
228 +
229 + if (len <= 0x7f) {
230 + this._buf[this._offset++] = len;
231 + } else if (len <= 0xff) {
232 + this._buf[this._offset++] = 0x81;
233 + this._buf[this._offset++] = len;
234 + } else if (len <= 0xffff) {
235 + this._buf[this._offset++] = 0x82;
236 + this._buf[this._offset++] = len >> 8;
237 + this._buf[this._offset++] = len;
238 + } else if (len <= 0xffffff) {
239 + this._buf[this._offset++] = 0x83;
240 + this._buf[this._offset++] = len >> 16;
241 + this._buf[this._offset++] = len >> 8;
242 + this._buf[this._offset++] = len;
243 + } else {
244 + throw new InvalidAsn1ERror('Length too long (> 4 bytes)');
245 + }
246 +};
247 +
248 +Writer.prototype.startSequence = function(tag) {
249 + if (typeof(tag) !== 'number')
250 + tag = ASN1.Sequence | ASN1.Constructor;
251 +
252 + this.writeByte(tag);
253 + this._seq.push(this._offset);
254 + this._ensure(3);
255 + this._offset += 3;
256 +};
257 +
258 +
259 +Writer.prototype.endSequence = function() {
260 + var seq = this._seq.pop();
261 + var start = seq + 3;
262 + var len = this._offset - start;
263 +
264 + if (len <= 0x7f) {
265 + this._shift(start, len, -2);
266 + this._buf[seq] = len;
267 + } else if (len <= 0xff) {
268 + this._shift(start, len, -1);
269 + this._buf[seq] = 0x81;
270 + this._buf[seq + 1] = len;
271 + } else if (len <= 0xffff) {
272 + this._buf[seq] = 0x82;
273 + this._buf[seq + 1] = len >> 8;
274 + this._buf[seq + 2] = len;
275 + } else if (len <= 0xffffff) {
276 + this._shift(start, len, 1);
277 + this._buf[seq] = 0x83;
278 + this._buf[seq + 1] = len >> 16;
279 + this._buf[seq + 2] = len >> 8;
280 + this._buf[seq + 3] = len;
281 + } else {
282 + throw new InvalidAsn1Error('Sequence too long');
283 + }
284 +};
285 +
286 +
287 +Writer.prototype._shift = function(start, len, shift) {
288 + assert.ok(start !== undefined);
289 + assert.ok(len !== undefined);
290 + assert.ok(shift);
291 +
292 + this._buf.copy(this._buf, start + shift, start, start + len);
293 + this._offset += shift;
294 +};
295 +
296 +Writer.prototype._ensure = function(len) {
297 + assert.ok(len);
298 +
299 + if (this._size - this._offset < len) {
300 + var sz = this._size * this._options.growthFactor;
301 + if (sz - this._offset < len)
302 + sz += len;
303 +
304 + var buf = new Buffer(sz);
305 +
306 + this._buf.copy(buf, 0, 0, this._offset);
307 + this._buf = buf;
308 + this._size = sz;
309 + }
310 +};
311 +
312 +
313 +
314 +///--- Exported API
315 +
316 +module.exports = Writer;
node.d/node_modules/net-snmp.js new
+1466
@@ -0,0 +1,1466 @@
1 +
2 +// Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
3 +
4 +var ber = require ("asn1").Ber;
5 +var dgram = require ("dgram");
6 +var events = require ("events");
7 +var util = require ("util");
8 +
9 +/*****************************************************************************
10 + ** Constants
11 + **/
12 +
13 +function _expandConstantObject (object) {
14 + var keys = [];
15 + for (key in object)
16 + keys.push (key);
17 + for (var i = 0; i < keys.length; i++)
18 + object[object[keys[i]]] = parseInt (keys[i]);
19 +}
20 +
21 +var ErrorStatus = {
22 + 0: "NoError",
23 + 1: "TooBig",
24 + 2: "NoSuchName",
25 + 3: "BadValue",
26 + 4: "ReadOnly",
27 + 5: "GeneralError",
28 + 6: "NoAccess",
29 + 7: "WrongType",
30 + 8: "WrongLength",
31 + 9: "WrongEncoding",
32 + 10: "WrongValue",
33 + 11: "NoCreation",
34 + 12: "InconsistentValue",
35 + 13: "ResourceUnavailable",
36 + 14: "CommitFailed",
37 + 15: "UndoFailed",
38 + 16: "AuthorizationError",
39 + 17: "NotWritable",
40 + 18: "InconsistentName"
41 +};
42 +
43 +_expandConstantObject (ErrorStatus);
44 +
45 +var ObjectType = {
46 + 1: "Boolean",
47 + 2: "Integer",
48 + 4: "OctetString",
49 + 5: "Null",
50 + 6: "OID",
51 + 64: "IpAddress",
52 + 65: "Counter",
53 + 66: "Gauge",
54 + 67: "TimeTicks",
55 + 68: "Opaque",
56 + 70: "Counter64",
57 + 128: "NoSuchObject",
58 + 129: "NoSuchInstance",
59 + 130: "EndOfMibView"
60 +};
61 +
62 +_expandConstantObject (ObjectType);
63 +
64 +ObjectType.Integer32 = ObjectType.Integer;
65 +ObjectType.Counter32 = ObjectType.Counter;
66 +ObjectType.Gauge32 = ObjectType.Gauge;
67 +ObjectType.Unsigned32 = ObjectType.Gauge32;
68 +
69 +var PduType = {
70 + 160: "GetRequest",
71 + 161: "GetNextRequest",
72 + 162: "GetResponse",
73 + 163: "SetRequest",
74 + 164: "Trap",
75 + 165: "GetBulkRequest",
76 + 166: "InformRequest",
77 + 167: "TrapV2",
78 + 168: "Report"
79 +};
80 +
81 +_expandConstantObject (PduType);
82 +
83 +var TrapType = {
84 + 0: "ColdStart",
85 + 1: "WarmStart",
86 + 2: "LinkDown",
87 + 3: "LinkUp",
88 + 4: "AuthenticationFailure",
89 + 5: "EgpNeighborLoss",
90 + 6: "EnterpriseSpecific"
91 +};
92 +
93 +_expandConstantObject (TrapType);
94 +
95 +var Version1 = 0;
96 +var Version2c = 1;
97 +
98 +/*****************************************************************************
99 + ** Exception class definitions
100 + **/
101 +
102 +function ResponseInvalidError (message) {
103 + this.name = "ResponseInvalidError";
104 + this.message = message;
105 + Error.captureStackTrace(this, ResponseInvalidError);
106 +}
107 +util.inherits (ResponseInvalidError, Error);
108 +
109 +function RequestInvalidError (message) {
110 + this.name = "RequestInvalidError";
111 + this.message = message;
112 + Error.captureStackTrace(this, RequestInvalidError);
113 +}
114 +util.inherits (RequestInvalidError, Error);
115 +
116 +function RequestFailedError (message, status) {
117 + this.name = "RequestFailedError";
118 + this.message = message;
119 + this.status = status;
120 + Error.captureStackTrace(this, RequestFailedError);
121 +}
122 +util.inherits (RequestFailedError, Error);
123 +
124 +function RequestTimedOutError (message) {
125 + this.name = "RequestTimedOutError";
126 + this.message = message;
127 + Error.captureStackTrace(this, RequestTimedOutError);
128 +}
129 +util.inherits (RequestTimedOutError, Error);
130 +
131 +/*****************************************************************************
132 + ** OID and varbind helper functions
133 + **/
134 +
135 +function isVarbindError (varbind) {
136 + if (varbind.type == ObjectType.NoSuchObject
137 + || varbind.type == ObjectType.NoSuchInstance
138 + || varbind.type == ObjectType.EndOfMibView)
139 + return true;
140 + else
141 + return false;
142 +}
143 +
144 +function varbindError (varbind) {
145 + return (ObjectType[varbind.type] || "NotAnError") + ": " + varbind.oid;
146 +}
147 +
148 +function oidFollowsOid (oidString, nextString) {
149 + var oid = {str: oidString, len: oidString.length, idx: 0};
150 + var next = {str: nextString, len: nextString.length, idx: 0};
151 + var dotCharCode = ".".charCodeAt (0);
152 +
153 + function getNumber (item) {
154 + var n = 0;
155 + if (item.idx >= item.len)
156 + return null;
157 + while (item.idx < item.len) {
158 + var charCode = item.str.charCodeAt (item.idx++);
159 + if (charCode == dotCharCode)
160 + return n;
161 + n = (n ? (n * 10) : n) + (charCode - 48);
162 + }
163 + return n;
164 + }
165 +
166 + while (1) {
167 + var oidNumber = getNumber (oid);
168 + var nextNumber = getNumber (next);
169 +
170 + if (oidNumber !== null) {
171 + if (nextNumber !== null) {
172 + if (nextNumber > oidNumber) {
173 + return true;
174 + } else if (nextNumber < oidNumber) {
175 + return false;
176 + }
177 + } else {
178 + return true;
179 + }
180 + } else {
181 + return true;
182 + }
183 + }
184 +}
185 +
186 +function oidInSubtree (oidString, nextString) {
187 + var oid = oidString.split (".");
188 + var next = nextString.split (".");
189 +
190 + if (oid.length > next.length)
191 + return false;
192 +
193 + for (var i = 0; i < oid.length; i++) {
194 + if (next[i] != oid[i])
195 + return false;
196 + }
197 +
198 + return true;
199 +}
200 +
201 +/**
202 + ** Some SNMP agents produce integers on the wire such as 00 ff ff ff ff.
203 + ** The ASN.1 BER parser we use throws an error when parsing this, which we
204 + ** believe is correct. So, we decided not to bother the "asn1" developer(s)
205 + ** with this, instead opting to work around it here.
206 + **
207 + ** If an integer is 5 bytes in length we check if the first byte is 0, and if so
208 + ** simply drop it and parse it like it was a 4 byte integer, otherwise throw
209 + ** an error since the integer is too large.
210 + **/
211 +
212 +function readInt (buffer) {
213 + return readUint (buffer, true);
214 +}
215 +
216 +function readUint (buffer, isSigned) {
217 + buffer.readByte ();
218 + var length = buffer.readByte ();
219 +
220 + if (length > 5) {
221 + throw new RangeError ("Integer too long '" + length + "'");
222 + } else if (length == 5) {
223 + if (buffer.readByte () !== 0)
224 + throw new RangeError ("Integer too long '" + length + "'");
225 + length = 4;
226 + }
227 +
228 + value = 0, signedBitSet = false;
229 +
230 + for (var i = 0; i < length; i++) {
231 + value *= 256;
232 + value += buffer.readByte ();
233 +
234 + if (isSigned && i <= 0) {
235 + if ((value & 0x80) == 0x80)
236 + signedBitSet = true;
237 + }
238 + }
239 +
240 + if (signedBitSet)
241 + value -= (1 << (i * 8));
242 +
243 + return value;
244 +}
245 +
246 +function readUint64 (buffer) {
247 + var value = buffer.readString (ObjectType.Counter64, true);
248 +
249 + if (value.length > 8)
250 + throw new RequestInvalidError ("64 bit unsigned integer too long '"
251 + + value.length + "'")
252 +
253 + return value;
254 +}
255 +
256 +function readVarbinds (buffer, varbinds) {
257 + buffer.readSequence ();
258 +
259 + while (1) {
260 + buffer.readSequence ();
261 + var oid = buffer.readOID ();
262 + var type = buffer.peek ();
263 +
264 + if (type == null)
265 + break;
266 +
267 + var value;
268 +
269 + if (type == ObjectType.Boolean) {
270 + value = buffer.readBoolean ();
271 + } else if (type == ObjectType.Integer) {
272 + value = readInt (buffer);
273 + } else if (type == ObjectType.OctetString) {
274 + value = buffer.readString (null, true);
275 + } else if (type == ObjectType.Null) {
276 + buffer.readByte ();
277 + buffer.readByte ();
278 + value = null;
279 + } else if (type == ObjectType.OID) {
280 + value = buffer.readOID ();
281 + } else if (type == ObjectType.IpAddress) {
282 + var bytes = buffer.readString (ObjectType.IpAddress, true);
283 + if (bytes.length != 4)
284 + throw new ResponseInvalidError ("Length '" + bytes.length
285 + + "' of IP address '" + bytes.toString ("hex")
286 + + "' is not 4");
287 + value = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
288 + } else if (type == ObjectType.Counter) {
289 + value = readUint (buffer);
290 + } else if (type == ObjectType.Gauge) {
291 + value = readUint (buffer);
292 + } else if (type == ObjectType.TimeTicks) {
293 + value = readUint (buffer);
294 + } else if (type == ObjectType.Opaque) {
295 + value = buffer.readString (ObjectType.Opaque, true);
296 + } else if (type == ObjectType.Counter64) {
297 + value = readUint64 (buffer);
298 + } else if (type == ObjectType.NoSuchObject) {
299 + buffer.readByte ();
300 + buffer.readByte ();
301 + value = null;
302 + } else if (type == ObjectType.NoSuchInstance) {
303 + buffer.readByte ();
304 + buffer.readByte ();
305 + value = null;
306 + } else if (type == ObjectType.EndOfMibView) {
307 + buffer.readByte ();
308 + buffer.readByte ();
309 + value = null;
310 + } else {
311 + throw new ResponseInvalidError ("Unknown type '" + type
312 + + "' in response");
313 + }
314 +
315 + varbinds.push ({
316 + oid: oid,
317 + type: type,
318 + value: value
319 + });
320 + }
321 +}
322 +
323 +function writeUint (buffer, type, value) {
324 + var b = new Buffer (4);
325 + b.writeUInt32BE (value, 0);
326 + buffer.writeBuffer (b, type);
327 +}
328 +
329 +function writeUint64 (buffer, value) {
330 + if (value.length > 8)
331 + throw new RequestInvalidError ("64 bit unsigned integer too long '"
332 + + value.length + "'")
333 + buffer.writeBuffer (value, ObjectType.Counter64);
334 +}
335 +
336 +function writeVarbinds (buffer, varbinds) {
337 + buffer.startSequence ();
338 + for (var i = 0; i < varbinds.length; i++) {
339 + buffer.startSequence ();
340 + buffer.writeOID (varbinds[i].oid);
341 +
342 + if (varbinds[i].type && varbinds[i].hasOwnProperty("value")) {
343 + var type = varbinds[i].type;
344 + var value = varbinds[i].value;
345 +
346 + if (type == ObjectType.Boolean) {
347 + buffer.writeBoolean (value ? true : false);
348 + } else if (type == ObjectType.Integer) { // also Integer32
349 + buffer.writeInt (value);
350 + } else if (type == ObjectType.OctetString) {
351 + if (typeof value == "string")
352 + buffer.writeString (value);
353 + else
354 + buffer.writeBuffer (value, ObjectType.OctetString);
355 + } else if (type == ObjectType.Null) {
356 + buffer.writeNull ();
357 + } else if (type == ObjectType.OID) {
358 + buffer.writeOID (value);
359 + } else if (type == ObjectType.IpAddress) {
360 + var bytes = value.split (".");
361 + if (bytes.length != 4)
362 + throw new RequestInvalidError ("Invalid IP address '"
363 + + value + "'");
364 + buffer.writeBuffer (new Buffer (bytes), 64);
365 + } else if (type == ObjectType.Counter) { // also Counter32
366 + writeUint (buffer, ObjectType.Counter, value);
367 + } else if (type == ObjectType.Gauge) { // also Gauge32 & Unsigned32
368 + writeUint (buffer, ObjectType.Gauge, value);
369 + } else if (type == ObjectType.TimeTicks) {
370 + writeUint (buffer, ObjectType.TimeTicks, value);
371 + } else if (type == ObjectType.Opaque) {
372 + buffer.writeBuffer (value, ObjectType.Opaque);
373 + } else if (type == ObjectType.Counter64) {
374 + writeUint64 (buffer, value);
375 + } else {
376 + throw new RequestInvalidError ("Unknown type '" + type
377 + + "' in request");
378 + }
379 + } else {
380 + buffer.writeNull ();
381 + }
382 +
383 + buffer.endSequence ();
384 + };
385 + buffer.endSequence ();
386 +}
387 +
388 +/*****************************************************************************
389 + ** PDU class definitions
390 + **/
391 +
392 +var SimplePdu = function (id, varbinds, options) {
393 + this.id = id;
394 + this.varbinds = varbinds;
395 + this.options = options || {};
396 +};
397 +
398 +SimplePdu.prototype.toBuffer = function (buffer) {
399 + buffer.startSequence (this.type);
400 +
401 + buffer.writeInt (this.id);
402 + buffer.writeInt ((this.type == PduType.GetBulkRequest)
403 + ? (this.options.nonRepeaters || 0)
404 + : 0);
405 + buffer.writeInt ((this.type == PduType.GetBulkRequest)
406 + ? (this.options.maxRepetitions || 0)
407 + : 0);
408 +
409 + writeVarbinds (buffer, this.varbinds);
410 +
411 + buffer.endSequence ();
412 +};
413 +
414 +var GetBulkRequestPdu = function () {
415 + this.type = PduType.GetBulkRequest;
416 + GetBulkRequestPdu.super_.apply (this, arguments);
417 +};
418 +
419 +util.inherits (GetBulkRequestPdu, SimplePdu);
420 +
421 +var GetNextRequestPdu = function () {
422 + this.type = PduType.GetNextRequest;
423 + GetNextRequestPdu.super_.apply (this, arguments);
424 +};
425 +
426 +util.inherits (GetNextRequestPdu, SimplePdu);
427 +
428 +var GetResponsePdu = function (buffer) {
429 + this.type = PduType.GetResponse;
430 +
431 + buffer.readSequence (this.type);
432 +
433 + this.id = buffer.readInt ();
434 +
435 + this.errorStatus = buffer.readInt ();
436 + this.errorIndex = buffer.readInt ();
437 +
438 + this.varbinds = [];
439 +
440 + readVarbinds (buffer, this.varbinds);
441 +};
442 +
443 +var GetRequestPdu = function () {
444 + this.type = PduType.GetRequest;
445 + GetRequestPdu.super_.apply (this, arguments);
446 +};
447 +
448 +util.inherits (GetRequestPdu, SimplePdu);
449 +
450 +var InformRequestPdu = function () {
451 + this.type = PduType.InformRequest;
452 + InformRequestPdu.super_.apply (this, arguments);
453 +};
454 +
455 +util.inherits (InformRequestPdu, SimplePdu);
456 +
457 +var SetRequestPdu = function () {
458 + this.type = PduType.SetRequest;
459 + SetRequestPdu.super_.apply (this, arguments);
460 +};
461 +
462 +util.inherits (SetRequestPdu, SimplePdu);
463 +
464 +var TrapPdu = function (typeOrOid, varbinds, options) {
465 + this.type = PduType.Trap;
466 +
467 + this.agentAddr = options.agentAddr || "127.0.0.1";
468 + this.upTime = options.upTime;
469 +
470 + if (typeof typeOrOid == "string") {
471 + this.generic = TrapType.EnterpriseSpecific;
472 + this.specific = parseInt (typeOrOid.match (/\.(\d+)$/)[1]);
473 + this.enterprise = typeOrOid.replace (/\.(\d+)$/, "");
474 + } else {
475 + this.generic = typeOrOid;
476 + this.specific = 0;
477 + this.enterprise = "1.3.6.1.4.1";
478 + }
479 +
480 + this.varbinds = varbinds;
481 +};
482 +
483 +TrapPdu.prototype.toBuffer = function (buffer) {
484 + buffer.startSequence (this.type);
485 +
486 + buffer.writeOID (this.enterprise);
487 + buffer.writeBuffer (new Buffer (this.agentAddr.split (".")),
488 + ObjectType.IpAddress);
489 + buffer.writeInt (this.generic);
490 + buffer.writeInt (this.specific);
491 + writeUint (buffer, ObjectType.TimeTicks,
492 + this.upTime || Math.floor (process.uptime () * 100));
493 +
494 + writeVarbinds (buffer, this.varbinds);
495 +
496 + buffer.endSequence ();
497 +};
498 +
499 +var TrapV2Pdu = function () {
500 + this.type = PduType.TrapV2;
501 + TrapV2Pdu.super_.apply (this, arguments);
502 +};
503 +
504 +util.inherits (TrapV2Pdu, SimplePdu);
505 +
506 +/*****************************************************************************
507 + ** Message class definitions
508 + **/
509 +
510 +var RequestMessage = function (version, community, pdu) {
511 + this.version = version;
512 + this.community = community;
513 + this.pdu = pdu;
514 +};
515 +
516 +RequestMessage.prototype.toBuffer = function () {
517 + if (this.buffer)
518 + return this.buffer;
519 +
520 + var writer = new ber.Writer ();
521 +
522 + writer.startSequence ();
523 +
524 + writer.writeInt (this.version);
525 + writer.writeString (this.community);
526 +
527 + this.pdu.toBuffer (writer);
528 +
529 + writer.endSequence ();
530 +
531 + this.buffer = writer.buffer;
532 +
533 + return this.buffer;
534 +};
535 +
536 +var ResponseMessage = function (buffer) {
537 + var reader = new ber.Reader (buffer);
538 +
539 + reader.readSequence ();
540 +
541 + this.version = reader.readInt ();
542 + this.community = reader.readString ();
543 +
544 + var type = reader.peek ();
545 +
546 + if (type == PduType.GetResponse) {
547 + this.pdu = new GetResponsePdu (reader);
548 + } else {
549 + throw new ResponseInvalidError ("Unknown PDU type '" + type
550 + + "' in response");
551 + }
552 +}
553 +
554 +/*****************************************************************************
555 + ** Session class definition
556 + **/
557 +
558 +var Session = function (target, community, options) {
559 + this.target = target || "127.0.0.1";
560 + this.community = community || "public";
561 +
562 + this.version = (options && options.version)
563 + ? options.version
564 + : Version1;
565 +
566 + this.transport = (options && options.transport)
567 + ? options.transport
568 + : "udp4";
569 + this.port = (options && options.port )
570 + ? options.port
571 + : 161;
572 + this.trapPort = (options && options.trapPort )
573 + ? options.trapPort
574 + : 162;
575 +
576 + this.retries = (options && (options.retries || options.retries == 0))
577 + ? options.retries
578 + : 1;
579 + this.timeout = (options && options.timeout)
580 + ? options.timeout
581 + : 5000;
582 +
583 + this.sourceAddress = (options && options.sourceAddress )
584 + ? options.sourceAddress
585 + : undefined;
586 + this.sourcePort = (options && options.sourcePort )
587 + ? parseInt(options.sourcePort)
588 + : undefined;
589 +
590 + this.reqs = {};
591 + this.reqCount = 0;
592 +
593 + this.dgram = dgram.createSocket (this.transport);
594 + this.dgram.unref();
595 +
596 + var me = this;
597 + this.dgram.on ("message", me.onMsg.bind (me));
598 + this.dgram.on ("close", me.onClose.bind (me));
599 + this.dgram.on ("error", me.onError.bind (me));
600 +
601 + if (this.sourceAddress || this.sourcePort)
602 + req.dgram.bind (this.sourcePort, this.sourceAddress);
603 +};
604 +
605 +util.inherits (Session, events.EventEmitter);
606 +
607 +Session.prototype.close = function () {
608 + this.dgram.close ();
609 + return this;
610 +}
611 +
612 +Session.prototype.cancelRequests = function (error) {
613 + for (id in this.reqs) {
614 + var req = this.reqs[id];
615 + this.unregisterRequest (req.id);
616 + req.responseCb (error);
617 + }
618 +}
619 +
620 +function _generateId () {
621 + return Math.floor (Math.random () + Math.random () * 10000000)
622 +}
623 +
624 +Session.prototype.get = function (oids, responseCb) {
625 + function feedCb (req, message) {
626 + var pdu = message.pdu;
627 + var varbinds = [];
628 +
629 + if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
630 + req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
631 + + "match response OIDs"));
632 + } else {
633 + for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
634 + if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
635 + req.responseCb (new ResponseInvalidError ("OID '"
636 + + req.message.pdu.varbinds[i].oid
637 + + "' in request at positiion '" + i + "' does not "
638 + + "match OID '" + pdu.varbinds[i].oid + "' in response "
639 + + "at position '" + i + "'"));
640 + return;
641 + } else {
642 + varbinds.push (pdu.varbinds[i]);
643 + }
644 + }
645 +
646 + req.responseCb (null, varbinds);
647 + }
648 + };
649 +
650 + var pduVarbinds = [];
651 +
652 + for (var i = 0; i < oids.length; i++) {
653 + var varbind = {
654 + oid: oids[i]
655 + };
656 + pduVarbinds.push (varbind);
657 + }
658 +
659 + this.simpleGet (GetRequestPdu, feedCb, pduVarbinds, responseCb);
660 +
661 + return this;
662 +};
663 +
664 +Session.prototype.getBulk = function () {
665 + var oids, nonRepeaters, maxRepetitions, responseCb;
666 +
667 + if (arguments.length >= 4) {
668 + oids = arguments[0];
669 + nonRepeaters = arguments[1];
670 + maxRepetitions = arguments[2];
671 + responseCb = arguments[3];
672 + } else if (arguments.length >= 3) {
673 + oids = arguments[0];
674 + nonRepeaters = arguments[1];
675 + maxRepetitions = 10;
676 + responseCb = arguments[2];
677 + } else {
678 + oids = arguments[0];
679 + nonRepeaters = 0;
680 + maxRepetitions = 10;
681 + responseCb = arguments[1];
682 + }
683 +
684 + function feedCb (req, message) {
685 + var pdu = message.pdu;
686 + var varbinds = [];
687 + var i = 0;
688 +
689 + // first walk through and grab non-repeaters
690 + if (pdu.varbinds.length < nonRepeaters) {
691 + req.responseCb (new ResponseInvalidError ("Varbind count in "
692 + + "response '" + pdu.varbinds.length + "' is less than "
693 + + "non-repeaters '" + nonRepeaters + "' in request"));
694 + } else {
695 + for ( ; i < nonRepeaters; i++) {
696 + if (isVarbindError (pdu.varbinds[i])) {
697 + varbinds.push (pdu.varbinds[i]);
698 + } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
699 + pdu.varbinds[i].oid)) {
700 + req.responseCb (new ResponseInvalidError ("OID '"
701 + + req.message.pdu.varbinds[i].oid + "' in request at "
702 + + "positiion '" + i + "' does not precede "
703 + + "OID '" + pdu.varbinds[i].oid + "' in response "
704 + + "at position '" + i + "'"));
705 + return;
706 + } else {
707 + varbinds.push (pdu.varbinds[i]);
708 + }
709 + }
710 + }
711 +
712 + var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
713 +
714 + // secondly walk through and grab repeaters
715 + if (pdu.varbinds.length % (repeaters)) {
716 + req.responseCb (new ResponseInvalidError ("Varbind count in "
717 + + "response '" + pdu.varbinds.length + "' is not a "
718 + + "multiple of repeaters '" + repeaters
719 + + "' plus non-repeaters '" + nonRepeaters + "' in request"));
720 + } else {
721 + while (i < pdu.varbinds.length) {
722 + for (var j = 0; j < repeaters; j++, i++) {
723 + var reqIndex = nonRepeaters + j;
724 + var respIndex = i;
725 +
726 + if (isVarbindError (pdu.varbinds[respIndex])) {
727 + if (! varbinds[reqIndex])
728 + varbinds[reqIndex] = [];
729 + varbinds[reqIndex].push (pdu.varbinds[respIndex]);
730 + } else if (! oidFollowsOid (
731 + req.message.pdu.varbinds[reqIndex].oid,
732 + pdu.varbinds[respIndex].oid)) {
733 + req.responseCb (new ResponseInvalidError ("OID '"
734 + + req.message.pdu.varbinds[reqIndex].oid
735 + + "' in request at positiion '" + (reqIndex)
736 + + "' does not precede OID '"
737 + + pdu.varbinds[respIndex].oid
738 + + "' in response at position '" + (respIndex) + "'"));
739 + return;
740 + } else {
741 + if (! varbinds[reqIndex])
742 + varbinds[reqIndex] = [];
743 + varbinds[reqIndex].push (pdu.varbinds[respIndex]);
744 + }
745 + }
746 + }
747 + }
748 +
749 + req.responseCb (null, varbinds);
750 + };
751 +
752 + var pduVarbinds = [];
753 +
754 + for (var i = 0; i < oids.length; i++) {
755 + var varbind = {
756 + oid: oids[i]
757 + };
758 + pduVarbinds.push (varbind);
759 + }
760 +
761 + var options = {
762 + nonRepeaters: nonRepeaters,
763 + maxRepetitions: maxRepetitions
764 + };
765 +
766 + this.simpleGet (GetBulkRequestPdu, feedCb, pduVarbinds, responseCb,
767 + options);
768 +
769 + return this;
770 +};
771 +
772 +Session.prototype.getNext = function (oids, responseCb) {
773 + function feedCb (req, message) {
774 + var pdu = message.pdu;
775 + var varbinds = [];
776 +
777 + if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
778 + req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
779 + + "match response OIDs"));
780 + } else {
781 + for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
782 + if (isVarbindError (pdu.varbinds[i])) {
783 + varbinds.push (pdu.varbinds[i]);
784 + } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
785 + pdu.varbinds[i].oid)) {
786 + req.responseCb (new ResponseInvalidError ("OID '"
787 + + req.message.pdu.varbinds[i].oid + "' in request at "
788 + + "positiion '" + i + "' does not precede "
789 + + "OID '" + pdu.varbinds[i].oid + "' in response "
790 + + "at position '" + i + "'"));
791 + return;
792 + } else {
793 + varbinds.push (pdu.varbinds[i]);
794 + }
795 + }
796 +
797 + req.responseCb (null, varbinds);
798 + }
799 + };
800 +
801 + var pduVarbinds = [];
802 +
803 + for (var i = 0; i < oids.length; i++) {
804 + var varbind = {
805 + oid: oids[i]
806 + };
807 + pduVarbinds.push (varbind);
808 + }
809 +
810 + this.simpleGet (GetNextRequestPdu, feedCb, pduVarbinds, responseCb);
811 +
812 + return this;
813 +};
814 +
815 +Session.prototype.inform = function () {
816 + var typeOrOid = arguments[0];;
817 + var varbinds, options = {}, responseCb;
818 +
819 + /**
820 + ** Support the following signatures:
821 + **
822 + ** typeOrOid, varbinds, options, callback
823 + ** typeOrOid, varbinds, callback
824 + ** typeOrOid, options, callback
825 + ** typeOrOid, callback
826 + **/
827 + if (arguments.length >= 4) {
828 + varbinds = arguments[1];
829 + options = arguments[2];
830 + responseCb = arguments[3];
831 + } else if (arguments.length >= 3) {
832 + if (arguments[1].constructor != Array) {
833 + varbinds = [];
834 + options = arguments[1];
835 + responseCb = arguments[2];
836 + } else {
837 + varbinds = arguments[1];
838 + responseCb = arguments[2];
839 + }
840 + } else {
841 + varbinds = [];
842 + responseCb = arguments[1];
843 + }
844 +
845 + function feedCb (req, message) {
846 + var pdu = message.pdu;
847 + var varbinds = [];
848 +
849 + if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
850 + req.responseCb (new ResponseInvalidError ("Inform OIDs do not "
851 + + "match response OIDs"));
852 + } else {
853 + for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
854 + if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
855 + req.responseCb (new ResponseInvalidError ("OID '"
856 + + req.message.pdu.varbinds[i].oid
857 + + "' in inform at positiion '" + i + "' does not "
858 + + "match OID '" + pdu.varbinds[i].oid + "' in response "
859 + + "at position '" + i + "'"));
860 + return;
861 + } else {
862 + varbinds.push (pdu.varbinds[i]);
863 + }
864 + }
865 +
866 + req.responseCb (null, varbinds);
867 + }
868 + };
869 +
870 + if (typeof typeOrOid != "string")
871 + typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
872 +
873 + var pduVarbinds = [
874 + {
875 + oid: "1.3.6.1.2.1.1.3.0",
876 + type: ObjectType.TimeTicks,
877 + value: options.upTime || Math.floor (process.uptime () * 100)
878 + },
879 + {
880 + oid: "1.3.6.1.6.3.1.1.4.1.0",
881 + type: ObjectType.OID,
882 + value: typeOrOid
883 + }
884 + ];
885 +
886 + for (var i = 0; i < varbinds.length; i++) {
887 + var varbind = {
888 + oid: varbinds[i].oid,
889 + type: varbinds[i].type,
890 + value: varbinds[i].value
891 + };
892 + pduVarbinds.push (varbind);
893 + }
894 +
895 + options.port = this.trapPort;
896 +
897 + this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
898 +
899 + return this;
900 +};
901 +
902 +Session.prototype.onClose = function () {
903 + this.cancelRequests (new Error ("Socket forcibly closed"));
904 + this.emit ("close");
905 +};
906 +
907 +Session.prototype.onError = function (error) {
908 + this.emit (error);
909 +};
910 +
911 +Session.prototype.onMsg = function (buffer, remote) {
912 + try {
913 + var message = new ResponseMessage (buffer);
914 + } catch (error) {
915 + this.emit("error", error);
916 + }
917 +
918 + var req = this.unregisterRequest (message.pdu.id);
919 + if (! req)
920 + return;
921 +
922 + try {
923 + if (message.version != req.message.version) {
924 + req.responseCb (req, new ResponseInvalidError ("Version in request '"
925 + + req.message.version + "' does not match version in "
926 + + "response '" + message.version));
927 + } else if (message.community != req.message.community) {
928 + req.responseCb (req, new ResponseInvalidError ("Community '"
929 + + req.message.community + "' in request does not match "
930 + + "community '" + message.community + "' in response"));
931 + } else if (message.pdu.type == PduType.GetResponse) {
932 + req.onResponse (req, message);
933 + } else {
934 + req.responseCb (req, new ResponseInvalidError ("Unknown PDU type '"
935 + + message.pdu.type + "' in response"));
936 + }
937 + } catch (error) {
938 + req.responseCb (req, error);
939 + }
940 +};
941 +
942 +Session.prototype.onSimpleGetResponse = function (req, message) {
943 + var pdu = message.pdu;
944 +
945 + if (pdu.errorStatus > 0) {
946 + var statusString = ErrorStatus[pdu.errorStatus]
947 + || ErrorStatus.GeneralError;
948 + var statusCode = ErrorStatus[statusString]
949 + || ErrorStatus[ErrorStatus.GeneralError];
950 +
951 + if (pdu.errorIndex <= 0 || pdu.errorIndex > pdu.varbinds.length) {
952 + req.responseCb (new RequestFailedError (statusString, statusCode));
953 + } else {
954 + var oid = pdu.varbinds[pdu.errorIndex - 1].oid;
955 + var error = new RequestFailedError (statusString + ": " + oid,
956 + statusCode);
957 + req.responseCb (error);
958 + }
959 + } else {
960 + req.feedCb (req, message);
961 + }
962 +};
963 +
964 +Session.prototype.registerRequest = function (req) {
965 + if (! this.reqs[req.id]) {
966 + this.reqs[req.id] = req;
967 + if (this.reqCount <= 0)
968 + this.dgram.ref();
969 + this.reqCount++;
970 + }
971 + var me = this;
972 + req.timer = setTimeout (function () {
973 + if (req.retries-- > 0) {
974 + me.send (req);
975 + } else {
976 + me.unregisterRequest (req.id);
977 + req.responseCb (new RequestTimedOutError (
978 + "Request timed out"));
979 + }
980 + }, req.timeout);
981 +};
982 +
983 +Session.prototype.send = function (req, noWait) {
984 + try {
985 + var me = this;
986 +
987 + var buffer = req.message.toBuffer ();
988 +
989 + this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
990 + function (error, bytes) {
991 + if (error) {
992 + req.responseCb (error);
993 + } else {
994 + if (noWait) {
995 + req.responseCb (null);
996 + } else {
997 + me.registerRequest (req);
998 + }
999 + }
1000 + });
1001 + } catch (error) {
1002 + req.responseCb (error);
1003 + }
1004 +
1005 + return this;
1006 +};
1007 +
1008 +Session.prototype.set = function (varbinds, responseCb) {
1009 + function feedCb (req, message) {
1010 + var pdu = message.pdu;
1011 + var varbinds = [];
1012 +
1013 + if (req.message.pdu.varbinds.length != pdu.varbinds.length) {
1014 + req.responseCb (new ResponseInvalidError ("Requested OIDs do not "
1015 + + "match response OIDs"));
1016 + } else {
1017 + for (var i = 0; i < req.message.pdu.varbinds.length; i++) {
1018 + if (req.message.pdu.varbinds[i].oid != pdu.varbinds[i].oid) {
1019 + req.responseCb (new ResponseInvalidError ("OID '"
1020 + + req.message.pdu.varbinds[i].oid
1021 + + "' in request at positiion '" + i + "' does not "
1022 + + "match OID '" + pdu.varbinds[i].oid + "' in response "
1023 + + "at position '" + i + "'"));
1024 + return;
1025 + } else {
1026 + varbinds.push (pdu.varbinds[i]);
1027 + }
1028 + }
1029 +
1030 + req.responseCb (null, varbinds);
1031 + }
1032 + };
1033 +
1034 + var pduVarbinds = [];
1035 +
1036 + for (var i = 0; i < varbinds.length; i++) {
1037 + var varbind = {
1038 + oid: varbinds[i].oid,
1039 + type: varbinds[i].type,
1040 + value: varbinds[i].value
1041 + };
1042 + pduVarbinds.push (varbind);
1043 + }
1044 +
1045 + this.simpleGet (SetRequestPdu, feedCb, pduVarbinds, responseCb);
1046 +
1047 + return this;
1048 +};
1049 +
1050 +Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
1051 + responseCb, options) {
1052 + var req = {}
1053 +
1054 + try {
1055 + var id = _generateId ();
1056 + var pdu = new pduClass (id, varbinds, options);
1057 + var message = new RequestMessage (this.version, this.community, pdu);
1058 +
1059 + req = {
1060 + id: id,
1061 + message: message,
1062 + responseCb: responseCb,
1063 + retries: this.retries,
1064 + timeout: this.timeout,
1065 + onResponse: this.onSimpleGetResponse,
1066 + feedCb: feedCb,
1067 + port: (options && options.port) ? options.port : this.port
1068 + };
1069 +
1070 + this.send (req);
1071 + } catch (error) {
1072 + if (req.responseCb)
1073 + req.responseCb (error);
1074 + }
1075 +};
1076 +
1077 +function subtreeCb (req, varbinds) {
1078 + var done = 0;
1079 +
1080 + for (var i = varbinds.length; i > 0; i--) {
1081 + if (! oidInSubtree (req.baseOid, varbinds[i - 1].oid)) {
1082 + done = 1;
1083 + varbinds.pop ();
1084 + }
1085 + }
1086 +
1087 + if (varbinds.length > 0)
1088 + req.feedCb (varbinds);
1089 +
1090 + if (done)
1091 + return true;
1092 +}
1093 +
1094 +Session.prototype.subtree = function () {
1095 + var me = this;
1096 + var oid = arguments[0];
1097 + var maxRepetitions, feedCb, doneCb;
1098 +
1099 + if (arguments.length < 4) {
1100 + maxRepetitions = 20;
1101 + feedCb = arguments[1];
1102 + doneCb = arguments[2];
1103 + } else {
1104 + maxRepetitions = arguments[1];
1105 + feedCb = arguments[2];
1106 + doneCb = arguments[3];
1107 + }
1108 +
1109 + var req = {
1110 + feedCb: feedCb,
1111 + doneCb: doneCb,
1112 + maxRepetitions: maxRepetitions,
1113 + baseOid: oid
1114 + };
1115 +
1116 + this.walk (oid, maxRepetitions, subtreeCb.bind (me, req), doneCb);
1117 +
1118 + return this;
1119 +}
1120 +
1121 +function tableColumnsResponseCb (req, error) {
1122 + if (error) {
1123 + req.responseCb (error);
1124 + } else if (req.error) {
1125 + req.responseCb (req.error);
1126 + } else {
1127 + if (req.columns.length > 0) {
1128 + var column = req.columns.pop ();
1129 + var me = this;
1130 + this.subtree (req.rowOid + column, req.maxRepetitions,
1131 + tableColumnsFeedCb.bind (me, req),
1132 + tableColumnsResponseCb.bind (me, req));
1133 + } else {
1134 + req.responseCb (null, req.table);
1135 + }
1136 + }
1137 +}
1138 +
1139 +function tableColumnsFeedCb (req, varbinds) {
1140 + for (var i = 0; i < varbinds.length; i++) {
1141 + if (isVarbindError (varbinds[i])) {
1142 + req.error = new RequestFailedError (varbindError (varbind[i]));
1143 + return true;
1144 + }
1145 +
1146 + var oid = varbinds[i].oid.replace (req.rowOid, "")
1147 + if (oid && oid != varbinds[i].oid) {
1148 + var match = oid.match (/^(\d+)\.(.+)$/);
1149 + if (match && match[1] > 0) {
1150 + if (! req.table[match[2]])
1151 + req.table[match[2]] = {};
1152 + req.table[match[2]][match[1]] = varbinds[i].value;
1153 + }
1154 + }
1155 + }
1156 +}
1157 +
1158 +Session.prototype.tableColumns = function () {
1159 + var me = this;
1160 +
1161 + var oid = arguments[0];
1162 + var columns = arguments[1];
1163 + var maxRepetitions, responseCb;
1164 +
1165 + if (arguments.length < 4) {
1166 + responseCb = arguments[2];
1167 + maxRepetitions = 20;
1168 + } else {
1169 + maxRepetitions = arguments[2];
1170 + responseCb = arguments[3];
1171 + }
1172 +
1173 + var req = {
1174 + responseCb: responseCb,
1175 + maxRepetitions: maxRepetitions,
1176 + baseOid: oid,
1177 + rowOid: oid + ".1.",
1178 + columns: columns.slice(0),
1179 + table: {}
1180 + };
1181 +
1182 + if (req.columns.length > 0) {
1183 + var column = req.columns.pop ();
1184 + this.subtree (req.rowOid + column, maxRepetitions,
1185 + tableColumnsFeedCb.bind (me, req),
1186 + tableColumnsResponseCb.bind (me, req));
1187 + }
1188 +
1189 + return this;
1190 +}
1191 +
1192 +function tableResponseCb (req, error) {
1193 + if (error)
1194 + req.responseCb (error);
1195 + else if (req.error)
1196 + req.responseCb (req.error);
1197 + else
1198 + req.responseCb (null, req.table);
1199 +}
1200 +
1201 +function tableFeedCb (req, varbinds) {
1202 + for (var i = 0; i < varbinds.length; i++) {
1203 + if (isVarbindError (varbinds[i])) {
1204 + req.error = new RequestFailedError (varbindError (varbind[i]));
1205 + return true;
1206 + }
1207 +
1208 + var oid = varbinds[i].oid.replace (req.rowOid, "")
1209 + if (oid && oid != varbinds[i].oid) {
1210 + var match = oid.match (/^(\d+)\.(.+)$/);
1211 + if (match && match[1] > 0) {
1212 + if (! req.table[match[2]])
1213 + req.table[match[2]] = {};
1214 + req.table[match[2]][match[1]] = varbinds[i].value;
1215 + }
1216 + }
1217 + }
1218 +}
1219 +
1220 +Session.prototype.table = function () {
1221 + var me = this;
1222 +
1223 + var oid = arguments[0];
1224 + var maxRepetitions, responseCb;
1225 +
1226 + if (arguments.length < 3) {
1227 + responseCb = arguments[1];
1228 + maxRepetitions = 20;
1229 + } else {
1230 + maxRepetitions = arguments[1];
1231 + responseCb = arguments[2];
1232 + }
1233 +
1234 + var req = {
1235 + responseCb: responseCb,
1236 + maxRepetitions: maxRepetitions,
1237 + baseOid: oid,
1238 + rowOid: oid + ".1.",
1239 + table: {}
1240 + };
1241 +
1242 + this.subtree (oid, maxRepetitions, tableFeedCb.bind (me, req),
1243 + tableResponseCb.bind (me, req));
1244 +
1245 + return this;
1246 +}
1247 +
1248 +Session.prototype.trap = function () {
1249 + var req = {};
1250 +
1251 + try {
1252 + var typeOrOid = arguments[0];
1253 + var varbinds, options = {}, responseCb;
1254 +
1255 + /**
1256 + ** Support the following signatures:
1257 + **
1258 + ** typeOrOid, varbinds, options, callback
1259 + ** typeOrOid, varbinds, agentAddr, callback
1260 + ** typeOrOid, varbinds, callback
1261 + ** typeOrOid, agentAddr, callback
1262 + ** typeOrOid, options, callback
1263 + ** typeOrOid, callback
1264 + **/
1265 + if (arguments.length >= 4) {
1266 + varbinds = arguments[1];
1267 + if (typeof arguments[2] == "string") {
1268 + options.agentAddr = arguments[2];
1269 + } else if (arguments[2].constructor != Array) {
1270 + options = arguments[2];
1271 + }
1272 + responseCb = arguments[3];
1273 + } else if (arguments.length >= 3) {
1274 + if (typeof arguments[1] == "string") {
1275 + varbinds = [];
1276 + options.agentAddr = arguments[1];
1277 + } else if (arguments[1].constructor != Array) {
1278 + varbinds = [];
1279 + options = arguments[1];
1280 + } else {
1281 + varbinds = arguments[1];
1282 + agentAddr = null;
1283 + }
1284 + responseCb = arguments[2];
1285 + } else {
1286 + varbinds = [];
1287 + responseCb = arguments[1];
1288 + }
1289 +
1290 + var pdu, pduVarbinds = [];
1291 +
1292 + for (var i = 0; i < varbinds.length; i++) {
1293 + var varbind = {
1294 + oid: varbinds[i].oid,
1295 + type: varbinds[i].type,
1296 + value: varbinds[i].value
1297 + };
1298 + pduVarbinds.push (varbind);
1299 + }
1300 +
1301 + var id = _generateId ();
1302 +
1303 + if (this.version == Version2c) {
1304 + if (typeof typeOrOid != "string")
1305 + typeOrOid = "1.3.6.1.6.3.1.1.5." + (typeOrOid + 1);
1306 +
1307 + pduVarbinds.unshift (
1308 + {
1309 + oid: "1.3.6.1.2.1.1.3.0",
1310 + type: ObjectType.TimeTicks,
1311 + value: options.upTime || Math.floor (process.uptime () * 100)
1312 + },
1313 + {
1314 + oid: "1.3.6.1.6.3.1.1.4.1.0",
1315 + type: ObjectType.OID,
1316 + value: typeOrOid
1317 + }
1318 + );
1319 +
1320 + pdu = new TrapV2Pdu (id, pduVarbinds, options);
1321 + } else {
1322 + pdu = new TrapPdu (typeOrOid, pduVarbinds, options);
1323 + }
1324 +
1325 + var message = new RequestMessage (this.version, this.community, pdu);
1326 +
1327 + req = {
1328 + id: id,
1329 + message: message,
1330 + responseCb: responseCb,
1331 + port: this.trapPort
1332 + };
1333 +
1334 + this.send (req, true);
1335 + } catch (error) {
1336 + if (req.responseCb)
1337 + req.responseCb (error);
1338 + }
1339 +
1340 + return this;
1341 +};
1342 +
1343 +Session.prototype.unregisterRequest = function (id) {
1344 + var req = this.reqs[id];
1345 + if (req) {
1346 + delete this.reqs[id];
1347 + clearTimeout (req.timer);
1348 + delete req.timer;
1349 + this.reqCount--;
1350 + if (this.reqCount <= 0)
1351 + this.dgram.unref();
1352 + return req;
1353 + } else {
1354 + return null;
1355 + }
1356 +};
1357 +
1358 +function walkCb (req, error, varbinds) {
1359 + var done = 0;
1360 + var oid;
1361 +
1362 + if (error) {
1363 + if (error instanceof RequestFailedError) {
1364 + if (error.status != ErrorStatus.NoSuchName) {
1365 + req.doneCb (error);
1366 + return;
1367 + } else {
1368 + // signal the version 1 walk code below that it should stop
1369 + done = 1;
1370 + }
1371 + } else {
1372 + req.doneCb (error);
1373 + return;
1374 + }
1375 + }
1376 +
1377 + if (this.version == Version2c) {
1378 + for (var i = varbinds[0].length; i > 0; i--) {
1379 + if (varbinds[0][i - 1].type == ObjectType.EndOfMibView) {
1380 + varbinds[0].pop ();
1381 + done = 1;
1382 + }
1383 + }
1384 + if (req.feedCb (varbinds[0]))
1385 + done = 1;
1386 + if (! done)
1387 + oid = varbinds[0][varbinds[0].length - 1].oid;
1388 + } else {
1389 + if (! done) {
1390 + if (req.feedCb (varbinds)) {
1391 + done = 1;
1392 + } else {
1393 + oid = varbinds[0].oid;
1394 + }
1395 + }
1396 + }
1397 +
1398 + if (done)
1399 + req.doneCb (null);
1400 + else
1401 + this.walk (oid, req.maxRepetitions, req.feedCb, req.doneCb,
1402 + req.baseOid);
1403 +}
1404 +
1405 +Session.prototype.walk = function () {
1406 + var me = this;
1407 + var oid = arguments[0];
1408 + var maxRepetitions, feedCb, doneCb, baseOid;
1409 +
1410 + if (arguments.length < 4) {
1411 + maxRepetitions = 20;
1412 + feedCb = arguments[1];
1413 + doneCb = arguments[2];
1414 + } else {
1415 + maxRepetitions = arguments[1];
1416 + feedCb = arguments[2];
1417 + doneCb = arguments[3];
1418 + }
1419 +
1420 + var req = {
1421 + maxRepetitions: maxRepetitions,
1422 + feedCb: feedCb,
1423 + doneCb: doneCb
1424 + };
1425 +
1426 + if (this.version == Version2c)
1427 + this.getBulk ([oid], 0, maxRepetitions,
1428 + walkCb.bind (me, req));
1429 + else
1430 + this.getNext ([oid], walkCb.bind (me, req));
1431 +
1432 + return this;
1433 +}
1434 +
1435 +/*****************************************************************************
1436 + ** Exports
1437 + **/
1438 +
1439 +exports.Session = Session;
1440 +
1441 +exports.createSession = function (target, community, version, options) {
1442 + return new Session (target, community, version, options);
1443 +};
1444 +
1445 +exports.isVarbindError = isVarbindError;
1446 +exports.varbindError = varbindError;
1447 +
1448 +exports.Version1 = Version1;
1449 +exports.Version2c = Version2c;
1450 +
1451 +exports.ErrorStatus = ErrorStatus;
1452 +exports.TrapType = TrapType;
1453 +exports.ObjectType = ObjectType;
1454 +
1455 +exports.ResponseInvalidError = ResponseInvalidError;
1456 +exports.RequestInvalidError = RequestInvalidError;
1457 +exports.RequestFailedError = RequestFailedError;
1458 +exports.RequestTimedOutError = RequestTimedOutError;
1459 +
1460 +/**
1461 + ** We've added this for testing.
1462 + **/
1463 +exports.ObjectParser = {
1464 + readInt: readInt,
1465 + readUint: readUint
1466 +};
node.d/node_modules/netdata.js
+105 -82
@@ -43,7 +43,7 @@ var netdata = {
43 options: {
44 filename: __filename,
45 DEBUG: false,
46 - update_every: 1000,
46 + update_every: 1,
47 },
48
49 chartAlgorithms: {
@@ -66,8 +66,61 @@ var netdata = {
66
67 processors: {
68 http: {
69 + name: 'http',
70
70 - },
71 + process: function(service, callback) {
72 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));
73 +
74 + var req = http.request(service.request, function(response) {
75 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
76 +
77 + var end = false;
78 + var data = '';
79 + response.setEncoding('utf8');
80 +
81 + if(response.statusCode !== 200) {
82 + if(end === false) {
83 + service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
84 + end = true;
85 + callback(null);
86 + }
87 + }
88 +
89 + response.on('data', function(chunk) {
90 + if(end === false) data += chunk;
91 + });
92 +
93 + response.on('error', function() {
94 + if(end === false) {
95 + service.error(': Read error, failed to get data.');
96 + end = true;
97 + callback(null);
98 + }
99 + });
100 +
101 + response.on('end', function() {
102 + if(end === false) {
103 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
104 + end = true;
105 + callback(data);
106 + }
107 + });
108 + });
109 +
110 + req.on('error', function(e) {
111 + service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
112 + callback(null);
113 + });
114 +
115 + // write data to request body
116 + if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {
117 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);
118 + req.write(service.postData);
119 + }
120 +
121 + req.end();
122 + }
123 + }
124 },
125
126 stringify: function(obj) {
@@ -108,6 +161,7 @@ var netdata = {
161 service.running = false;
162 service.started = 0;
163 service.ended = 0;
164 + service.next_run = new Date().getTime();
165
166 if(typeof service.update_every === 'undefined')
167 service.update_every = service.module.update_every;
@@ -118,106 +172,70 @@ var netdata = {
172 if(typeof service.processor === 'undefined')
173 service.processor = netdata.processors.http;
174
175 + if(service.update_every < netdata.options.update_every)
176 + service.update_every = netdata.options.update_every;
177 +
178 service.commit = function() {
179 if(this.added !== true) {
180 this.added = true;
181 +
182 + var now = new Date().getTime();
183 + while( this.next_run < now )
184 + this.next_run += (this.update_every * 1000);
185 +
186 netdata.services.push(this);
187 if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');
188 }
189 };
190
129 - service._processResponse = function(response, callback) {
130 - this.running = false;
131 - this.ended = new Date().getTime();
132 -
133 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': processing response (received it in ' + (this.ended - this.started).toString() + ' ms)');
134 -
135 - callback(this, response);
136 -
137 - this.module.active--;
138 - if(this.module.active < 0) {
139 - this.module.active = 0;
140 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': active module counter below zero.');
141 - }
142 -
143 - if(this.module.active === 0) {
144 - // check if we run under configure
145 - if(this.module.configure_callback !== null) {
146 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': configuration finish callback called from processResponse().');
147 - var ccallback = this.module.configure_callback;
148 - this.module.configure_callback = null;
149 - ccallback();
150 - }
151 - }
152 - };
153 -
191 service.execute = function(callback) {
192 this.module.active++;
193 this.running = true;
194 this.started = new Date().getTime();
195 this.updates++;
196
160 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': making request: ' + netdata.stringify(this.request));
197 + if(netdata.options.DEBUG === true)
198 + netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));
199
162 - var req = http.request(this.request, function(response) {
163 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
200 + this.processor.process(this, function(response) {
201 + service.ended = new Date().getTime();
202 + service.duration = service.ended - service.started;
203
165 - var end = false;
166 - var data = '';
167 - response.setEncoding('utf8');
204 + if(typeof response === 'undefined')
205 + response = null;
206
169 - if(response.statusCode !== 200) {
170 - if(end === false) {
171 - service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
172 - end = true;
173 - service._processResponse(null, callback);
174 - }
175 - }
207 + if(response !== null)
208 + service.errorClear();
209
177 - response.on('data', function(chunk) {
178 - if(end === false) data += chunk;
179 - });
210 + if(netdata.options.DEBUG === true)
211 + netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');
212
181 - response.on('error', function() {
182 - if(end === false) {
183 - service.error(': Read error, failed to get data.');
184 - end = true;
185 - service._processResponse(null, callback);
186 - }
187 - });
213 + callback(service, response);
214
189 - response.on('end', function() {
190 - if(end === false) {
191 - service.errorClear();
192 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
193 - end = true;
194 - service._processResponse(data, callback);
195 - }
196 - });
197 - });
215 + service.running = false;
216 + service.module.active--;
217 + if(service.module.active < 0) {
218 + service.module.active = 0;
219 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');
220 + }
221
199 - req.on('error', function(e) {
200 - service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
201 - service._processResponse(null, callback);
222 + if(service.module.active === 0) {
223 + // check if we run under configure
224 + if(service.module.configure_callback !== null) {
225 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');
226 + var ccallback = service.module.configure_callback;
227 + service.module.configure_callback = null;
228 + ccallback();
229 + }
230 + }
231 });
203 -
204 - // write data to request body
205 - if(typeof this.postData !== 'undefined' && this.request.method === 'POST') {
206 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': posting data: ' + this.postData);
207 - req.write(this.postData);
208 - }
209 -
210 - req.end();
232 };
233
234 service.update = function() {
235 if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');
236
237 this.module.update(this, function() {
217 - service.ended = new Date().getTime();
218 - service.duration = service.ended - service.started;
238 if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');
220 - service.running = false;
239 });
240 };
241
@@ -345,7 +363,7 @@ var netdata = {
363 if(typeof(netdata.charts[id]) === 'undefined') {
364 netdata.charts[id] = {
365 _created: false,
348 - _updated: false,
366 + _updated: true,
367 _began: false,
368 _counter: 0,
369 _last_updated: 0,
@@ -354,8 +372,8 @@ var netdata = {
372 name: id,
373 title: 'untitled chart',
374 units: 'a unit',
357 - family: id,
358 - category: id,
375 + family: '',
376 + category: '',
377 type: netdata.chartTypes.line,
378 priority: 0,
379 update_every: netdata.options.update_every,
@@ -408,7 +426,7 @@ var netdata = {
426 }
427
428 if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {
411 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every');
429 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);
430 c.update_every = chart.update_every;
431 c._updated = true;
432 }
@@ -486,16 +504,21 @@ var netdata = {
504 var service = netdata.services[len];
505
506 if(service.enabled === false || service.running === true) continue;
489 - if(now - service.ended < service.update_every) continue;
507 + if(now <= service.next_run) continue;
508
509 service.update();
510 +
511 + now = new Date().getTime();
512 + while(service.next_run < now)
513 + service.next_run += (service.update_every * 1000);
514 }
515
494 - setTimeout(netdata.runAllServices, 100);
516 + // 1/10th of update_every in pause
517 + setTimeout(netdata.runAllServices, netdata.options.update_every * 100);
518 },
519
520 start: function() {
498 - if(netdata.options.DEBUG === true) this.debug('started, services:');
521 + if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));
522
523 if(this.services.length === 0) {
524 this.disableNodePlugin();
@@ -524,7 +547,7 @@ var netdata = {
547 },
548 agent: new http.Agent({
549 keepAlive: true,
527 - keepAliveMsecs: netdata.options.update_every,
550 + keepAliveMsecs: netdata.options.update_every * 1000,
551 maxSockets: 2, // it must be 2 to work
552 maxFreeSockets: 1
553 })
@@ -543,7 +566,7 @@ var netdata = {
566 module.update_every = this.options.update_every;
567
568 if(typeof config.update_every !== 'undefined')
546 - module.update_every = config.update_every * 1000;
569 + module.update_every = config.update_every;
570
571 module.enable_autodetect = (config.enable_autodetect)?true:false;
572
node.d/sma_webbox.node.js
+6 -8
@@ -32,7 +32,7 @@ if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plug
32 var webbox = {
33 name: __filename,
34 enable_autodetect: true,
35 - update_every: 1000,
35 + update_every: 1,
36
37 charts: {},
38
@@ -87,7 +87,7 @@ var webbox = {
87 category: 'sma_webbox_' + service.name, // the category of the chart
88 type: netdata.chartTypes.area, // the type of the chart
89 priority: 1000, // the priority relative to others in the same family and category
90 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
90 + update_every: service.update_every, // the expected update frequency of the chart
91 dimensions: {
92 'GriPwr': {
93 id: 'GriPwr', // the unique id of the dimension
@@ -123,7 +123,7 @@ var webbox = {
123 category: 'sma_webbox_' + service.name, // the category of the chart
124 type: netdata.chartTypes.area, // the type of the chart
125 priority: 1000, // the priority relative to others in the same family and category
126 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
126 + update_every: service.update_every, // the expected update frequency of the chart
127 dimensions: {
128 'GriEgyTdy': {
129 id: 'GriEgyTdy', // the unique id of the dimension
@@ -159,7 +159,7 @@ var webbox = {
159 category: 'sma_webbox_' + service.name, // the category of the chart
160 type: netdata.chartTypes.area, // the type of the chart
161 priority: 1000, // the priority relative to others in the same family and category
162 - update_every: Math.round(service.update_every / 1000), // the expected update frequency of the chart
162 + update_every: service.update_every, // the expected update frequency of the chart
163 dimensions: {
164 'GriEgyTot': {
165 id: 'GriEgyTot', // the unique id of the dimension
@@ -211,11 +211,9 @@ var webbox = {
211 while(len--) {
212 if(typeof config.servers[len].update_every === 'undefined')
213 config.servers[len].update_every = this.update_every;
214 - else
215 - config.servers[len].update_every = config.servers[len].update_every * 1000;
214
217 - if(config.servers[len].update_every < 5000)
218 - config.servers[len].update_every = 5000;
215 + if(config.servers[len].update_every < 5)
216 + config.servers[len].update_every = 5;
217
218 this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every);
219 added++;
node.d/snmp.node.js new
+327
@@ -0,0 +1,327 @@
1 +'use strict';
2 +
3 +// This program will connect to one or more SNMP Agents
4 +
5 +// example configuration in /etc/netdata/snmp.conf
6 +/*
7 +{
8 + "enable_autodetect": false,
9 + "update_every": 5,
10 + "servers": [
11 + {
12 + "hostname": "10.11.12.8",
13 + "community": "public",
14 + "update_every": 10,
15 + "options": { "timeout": 10000 },
16 + "charts": {
17 + "snmp_switch.bandwidth_port1": {
18 + "title": "Switch Bandwidth for port 1",
19 + "units": "kilobits/s",
20 + "type": "area",
21 + "priority": 1,
22 + "dimensions": {
23 + "in": {
24 + "oid": ".1.3.6.1.2.1.2.2.1.10.1",
25 + "algorithm": "incremental",
26 + "multiplier": 8,
27 + "divisor": 1024
28 + },
29 + "out": {
30 + "oid": ".1.3.6.1.2.1.2.2.1.16.1",
31 + "algorithm": "incremental",
32 + "multiplier": -8,
33 + "divisor": 1024
34 + }
35 + }
36 + },
37 + "snmp_switch.bandwidth_port2": {
38 + "title": "Switch Bandwidth for port 2",
39 + "units": "kilobits/s",
40 + "type": "area",
41 + "priority": 1,
42 + "dimensions": {
43 + "in": {
44 + "oid": ".1.3.6.1.2.1.2.2.1.10.2",
45 + "algorithm": "incremental",
46 + "multiplier": 8,
47 + "divisor": 1024
48 + },
49 + "out": {
50 + "oid": ".1.3.6.1.2.1.2.2.1.16.2",
51 + "algorithm": "incremental",
52 + "multiplier": -8,
53 + "divisor": 1024
54 + }
55 + }
56 + }
57 + }
58 + }
59 + ]
60 +}
61 +*/
62 +
63 +// You can also give ranges of charts like the following.
64 +// This will append 1-24 to id, title, oid (on each dimension)
65 +// so that 24 charts will be created.
66 +/*
67 +{
68 + "enable_autodetect": false,
69 + "update_every": 10,
70 + "servers": [
71 + {
72 + "hostname": "10.11.12.8",
73 + "community": "public",
74 + "update_every": 10,
75 + "options": { "timeout": 20000 },
76 + "charts": {
77 + "snmp_switch.bandwidth_port": {
78 + "title": "Switch Bandwidth for port ",
79 + "units": "kilobits/s",
80 + "type": "area",
81 + "priority": 1,
82 + "multiply_range": [ 1, 24 ],
83 + "dimensions": {
84 + "in": {
85 + "oid": "1.3.6.1.2.1.2.2.1.10",
86 + "algorithm": "incremental",
87 + "multiplier": 8,
88 + "divisor": 1024
89 + },
90 + "out": {
91 + "oid": "1.3.6.1.2.1.2.2.1.16",
92 + "algorithm": "incremental",
93 + "multiplier": -8,
94 + "divisor": 1024
95 + }
96 + }
97 + }
98 + }
99 + }
100 + ]
101 +}
102 +*/
103 +
104 +var net_snmp = require('net-snmp');
105 +var extend = require('extend');
106 +var netdata = require('netdata');
107 +
108 +if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
109 +
110 +netdata.processors.snmp = {
111 + name: 'snmp',
112 +
113 + process: function(service, callback) {
114 + if(typeof service.snmp_oids === 'undefined' || service.snmp_oids === null || service.snmp_oids.length === 0) {
115 + // this is the first time we see this service
116 +
117 + if(netdata.options.DEBUG === true)
118 + netdata.debug(service.module.name + ': ' + service.name + ': preparing ' + this.name + ' OIDs');
119 +
120 + // build an index of all OIDs
121 + service.snmp_oids_index = {};
122 + for(var c in service.request.charts) {
123 + // for each chart
124 +
125 + if(netdata.options.DEBUG === true)
126 + netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c);
127 +
128 + for(var d in service.request.charts[c].dimensions) {
129 + // for each dimension in the chart
130 +
131 + if(netdata.options.DEBUG === true)
132 + netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c + ', dimension: ' + d + ', OID: ' + service.request.charts[c].dimensions[d].oid);
133 +
134 + // link it to the point we need to set the value to
135 + service.snmp_oids_index[service.request.charts[c].dimensions[d].oid] = service.request.charts[c].dimensions[d];
136 +
137 + // and set the value to null
138 + service.request.charts[c].dimensions[d].value = null;
139 + }
140 + }
141 + if(netdata.options.DEBUG === true)
142 + netdata.debug(service.module.name + ': ' + service.name + ': indexed ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids_index));
143 +
144 + // now create the array of OIDs needed by net-snmp
145 + service.snmp_oids = new Array();
146 + for(var o in service.snmp_oids_index)
147 + service.snmp_oids.push(o);
148 +
149 + if(netdata.options.DEBUG === true)
150 + netdata.debug(service.module.name + ': ' + service.name + ': final list of ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids));
151 + }
152 +
153 + if(service.snmp_oids.length === 0) {
154 + // no OIDs found for this service
155 +
156 + if(netdata.options.DEBUG === true)
157 + service.error('no OIDs to process.');
158 +
159 + callback(null);
160 + return;
161 + }
162 +
163 + if(typeof service.snmp_session === 'undefined' || service.snmp_session === null) {
164 + // no SNMP session has been created for this service
165 + // the SNMP session is just the initialization of NET-SNMP
166 +
167 + if(netdata.options.DEBUG === true)
168 + netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
169 +
170 + // create the SNMP session
171 + service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
172 +
173 + if(netdata.options.DEBUG === true)
174 + netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));
175 +
176 + // if we later need traps, this is how to do it:
177 + //service.snmp_session.trap(net_snmp.TrapType.LinkDown, function(error) {
178 + // if(error) console.error('trap error: ' + netdata.stringify(error));
179 + //});
180 + }
181 +
182 + // do it, get the SNMP values for the sessions we need
183 + service.snmp_session.get(service.snmp_oids, function(error, varbinds) {
184 + var ok = 0, failed = 0;
185 +
186 + if(error) {
187 + service.error('Received error = ' + netdata.stringify(error) + ' varbinds = ' + netdata.stringify(varbinds));
188 + }
189 + else {
190 + if(netdata.options.DEBUG === true)
191 + netdata.debug(service.module.name + ': ' + service.name + ': got valid ' + service.module.name + ' response: ' + netdata.stringify(varbinds));
192 +
193 + for(var i = 0; i < varbinds.length; i++) {
194 + if(net_snmp.isVarbindError(varbinds[i])) {
195 + if(netdata.options.DEBUG === true)
196 + netdata.debug(service.module.name + ': ' + service.name + ': failed ' + service.module.name + ' get for OIDs ' + varbinds[i].oid);
197 +
198 + service.error('OID ' + varbinds[i].oid + ' gave error: ' + snmp.varbindError(varbinds[i]));
199 + service.snmp_oids_index[varbinds[i].oid].value = null;
200 + failed++;
201 + }
202 + else {
203 + if(netdata.options.DEBUG === true)
204 + netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
205 +
206 + service.snmp_oids_index[varbinds[i].oid].value = varbinds[i].value;
207 + ok++;
208 + }
209 + }
210 +
211 + if(netdata.options.DEBUG === true)
212 + netdata.debug(service.module.name + ': ' + service.name + ': finished ' + service.module.name + ' with ' + ok + ' successful and ' + failed + ' failed values');
213 + }
214 +
215 + callback((ok > 0)?{ ok: ok, failed: failed }:null);
216 + });
217 + }
218 +};
219 +
220 +var snmp = {
221 + name: __filename,
222 + enable_autodetect: true,
223 + update_every: 1,
224 +
225 + charts: {},
226 +
227 + processResponse: function(service, data) {
228 + if(data !== null) {
229 + if(service.added !== true)
230 + service.commit();
231 +
232 + for(var c in service.request.charts) {
233 + var chart = snmp.charts[c];
234 +
235 + if(typeof chart === 'undefined') {
236 + chart = service.chart(c, service.request.charts[c]);
237 + snmp.charts[c] = chart;
238 + }
239 +
240 + service.begin(chart);
241 +
242 + for( var d in service.request.charts[c].dimensions )
243 + if(service.request.charts[c].dimensions[d].value !== null)
244 + service.set(d, service.request.charts[c].dimensions[d].value);
245 +
246 + service.end();
247 + }
248 + }
249 + },
250 +
251 + // module.serviceExecute()
252 + // this function is called only from this module
253 + // its purpose is to prepare the request and call
254 + // netdata.serviceExecute()
255 + serviceExecute: function(conf) {
256 + if(netdata.options.DEBUG === true)
257 + netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', update_every: ' + conf.update_every);
258 +
259 + var service = netdata.service({
260 + name: conf.hostname,
261 + request: conf,
262 + update_every: conf.update_every,
263 + module: this,
264 + processor: netdata.processors.snmp
265 + });
266 +
267 + // multiply the charts, if required
268 + for(var c in service.request.charts) {
269 + if(netdata.options.DEBUG === true)
270 + netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', examining chart: ' + c);
271 +
272 + if(typeof service.request.charts[c].update_every === 'undefined')
273 + service.request.charts[c].update_every = service.update_every;
274 +
275 + if(typeof service.request.charts[c].multiply_range !== 'undefined') {
276 + var from = service.request.charts[c].multiply_range[0];
277 + var to = service.request.charts[c].multiply_range[1];
278 + var prio = service.request.charts[c].priority || 1;
279 +
280 + while(from <= to) {
281 + var id = c + from.toString();
282 + var chart = extend(true, {}, service.request.charts[c]);
283 + chart.title += from.toString();
284 + chart.priority = prio++;
285 + for(var d in chart.dimensions) {
286 + chart.dimensions[d].oid += '.' + from.toString();
287 + }
288 + service.request.charts[id] = chart;
289 + from++;
290 + }
291 +
292 + delete service.request.charts[c];
293 + }
294 + }
295 +
296 + service.execute(this.processResponse);
297 + },
298 +
299 + configure: function(config) {
300 + var added = 0;
301 +
302 + if(typeof(config.servers) !== 'undefined') {
303 + var len = config.servers.length;
304 + while(len--) {
305 + if(typeof config.servers[len].update_every === 'undefined')
306 + config.servers[len].update_every = this.update_every;
307 +
308 + this.serviceExecute(config.servers[len]);
309 + added++;
310 + }
311 + }
312 +
313 + return added;
314 + },
315 +
316 + // module.update()
317 + // this is called repeatidly to collect data, by calling
318 + // service.execute()
319 + update: function(service, callback) {
320 + service.execute(function(serv, data) {
321 + service.module.processResponse(serv, data);
322 + callback();
323 + });
324 + },
325 +};
326 +
327 +module.exports = snmp;
plugins.d/node.d.plugin
+7 -7
@@ -9,7 +9,6 @@ var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
9 var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || '/etc/netdata';
10 var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
11 var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';
12 -NETDATA_UPDATE_EVERY = NETDATA_UPDATE_EVERY * 1000;
12
13 // make sure the modules are found
14 process.mainModule.paths.unshift(NODE_D_DIR + '/node_modules');
@@ -133,14 +132,14 @@ function dumpError(err) {
132 try {
133 var x = parseInt(val);
134 if(x > 0) {
136 - netdata.options.update_every = x * 1000;
135 + netdata.options.update_every = x;
136 if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
137 netdata.options.update_every = NETDATA_UPDATE_EVERY;
138 netdata.debug('Update frequency ' + x + 's is too low');
139 }
140
141 found_number = true;
143 - netdata.debug('Update frequency set to ' + netdata.options.update_every + ' ms');
142 + netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
143 }
144 else netdata.error('Ignoring parameter: ' + val);
145 }
@@ -155,9 +154,9 @@ function dumpError(err) {
154 });
155 }
156
158 -if(netdata.options.update_every < 1000) {
157 +if(netdata.options.update_every < 1) {
158 netdata.debug('Adjusting update frequency to 1 second');
160 - netdata.options.update_every = 1000;
159 + netdata.options.update_every = 1;
160 }
161
162 // --------------------------------------------------------------------------------------------------------------------
@@ -174,7 +173,7 @@ function findModules() {
173 var n = files[len].substring(0, m.index);
174
175 if(typeof(netdata.options.modules[n]) === 'undefined')
177 - netdata.options.modules[n] = { enabled: netdata.options.modules_enable_all };
176 + netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
177
178 if(netdata.options.modules[n].enabled === true) {
179 netdata.options.modules[n].name = n;
@@ -201,7 +200,7 @@ function findModules() {
200 // load its configuration
201 var c = {
202 enable_autodetect: netdata.options.modules_enable_autodetect,
204 - update_every: Math.round(netdata.options.update_every / 1000)
203 + update_every: netdata.options.update_every
204 };
205 try {
206 netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
@@ -239,6 +238,7 @@ function findModules() {
238 }
239 }
240
241 + // netdata.debug(netdata.options.modules);
242 return found;
243 }
244