标签:
var assert = require(‘assert‘); var ASN1 = { EOC: 0, Boolean: 1, Integer: 2, BitString: 3, OctetString: 4, Null: 5, OID: 6, ObjectDescriptor: 7, External: 8, Real: 9, // float Enumeration: 10, PDV: 11, Utf8String: 12, RelativeOID: 13, Sequence: 16, Set: 17, NumericString: 18, PrintableString: 19, T61String: 20, VideotexString: 21, IA5String: 22, UTCTime: 23, GeneralizedTime: 24, GraphicString: 25, VisibleString: 26, GeneralString: 28, UniversalString: 29, CharacterString: 30, BMPString: 31, Constructor: 32, Context: 128, TypeError: function(msg) { var e = new Error(); e.name = ‘InvalidAsn1Error‘; e.message = msg || ‘‘; return e; } }; function Reader(data) { if (!data || !Buffer.isBuffer(data)) throw new TypeError(‘data must be a node Buffer‘); this._buf = data; this._size = data.length; // These hold the "current" state this._len = 0; this._offset = 0; var self = this; this.__defineGetter__(‘length‘, function() { return self._len; }); this.__defineGetter__(‘offset‘, function() { return self._offset; }); this.__defineGetter__(‘remain‘, function() { return self._size - self._offset; }); this.__defineGetter__(‘buffer‘, function() { return self._buf.slice(self._offset); }); } /** * Reads a single byte and advances offset; you can pass in `true` to make this * a "peek" operation (i.e., get the byte, but don‘t advance the offset). * * @param {Boolean} peek true means don‘t move offset. * @return {Number} the next byte, null if not enough data. */ Reader.prototype.readByte = function(peek) { if (this._size - this._offset < 1) return null; var b = this._buf[this._offset] & 0xff; if (!peek) this._offset += 1; return b; }; Reader.prototype.peek = function() { return this.readByte(true); }; /** * Reads a (potentially) variable length off the BER buffer. This call is * not really meant to be called directly, as callers have to manipulate * the internal buffer afterwards. * * As a result of this call, you can call `Reader.length`, until the * next thing called that does a readLength. * * @return {Number} the amount of offset to advance the buffer. * @throws {InvalidAsn1Error} on bad ASN.1 */ Reader.prototype.readLength = function(offset) { if (offset === undefined) offset = this._offset; if (offset >= this._size) return null; var lenB = this._buf[offset++] & 0xff; if (lenB === null) return null; if ((lenB & 0x80) == 0x80) { lenB &= 0x7f; if (lenB == 0) throw ASN1.TypeError(‘Indefinite length not supported‘); if (lenB > 4) throw ASN1.TypeError(‘encoding too long‘); if (this._size - offset < lenB) return null; this._len = 0; for (var i = 0; i < lenB; i++) this._len = (this._len << 8) + (this._buf[offset++] & 0xff); } else { // Wasn‘t a variable length this._len = lenB; } return offset; }; /** * Parses the next sequence in this BER buffer. * * To get the length of the sequence, call `Reader.length`. * * @return {Number} the sequence‘s tag. */ Reader.prototype.readSequence = function(tag) { var seq = this.peek(); if (seq === null) return null; if (tag !== undefined && tag !== seq) throw ASN1.TypeError(‘Expected 0x‘ + tag.toString(16) + ‘: got 0x‘ + seq.toString(16)); var o = this.readLength(this._offset + 1); // stored in `length` if (o === null) return null; this._offset = o; return seq; }; Reader.prototype.readInt = function() { return this.readTag(ASN1.Integer); }; Reader.prototype.readBoolean = function() { return (this.readTag(ASN1.Boolean) === 0 ? false : true); }; Reader.prototype.readEnumeration = function() { return this.readTag(ASN1.Enumeration); }; Reader.prototype.readString = function(tag, retbuf) { if (!tag) tag = ASN1.OctetString; var b = this.peek(); if (b === null) return null; if (b !== tag) throw ASN1.TypeError(‘Expected 0x‘ + tag.toString(16) + ‘: got 0x‘ + b.toString(16)); var o = this.readLength(this._offset + 1); // stored in `length` if (o === null) return null; if (this.length > this._size - o) return null; this._offset = o; if (this.length === 0) return retbuf ? new Buffer(0) : ‘‘; var str = this._buf.slice(this._offset, this._offset + this.length); this._offset += this.length; return retbuf ? str : str.toString(‘utf8‘); }; Reader.prototype.readOID = function(tag) { if (!tag) tag = ASN1.OID; var b = this.readString(tag, true); if (b === null) return null; var values = []; var value = 0; for (var i = 0; i < b.length; i++) { var byte = b[i] & 0xff; value <<= 7; value += byte & 0x7f; if ((byte & 0x80) == 0) { values.push(value); value = 0; } } value = values.shift(); values.unshift(value % 40); values.unshift((value / 40) >> 0); return values.join(‘.‘); }; Reader.prototype.readTag = function(tag) { assert.ok(tag !== undefined); var b = this.peek(); if (b === null) return null; if (b !== tag) throw ASN1.TypeError(‘Expected 0x‘ + tag.toString(16) + ‘: got 0x‘ + b.toString(16)); var o = this.readLength(this._offset + 1); // stored in `length` if (o === null) return null; if (this.length > 4) throw ASN1.TypeError(‘Integer too long: ‘ + this.length); if (this.length > this._size - o) return null; this._offset = o; var fb = this._buf[this._offset]; var value = 0; for (var i = 0; i < this.length; i++) { value <<= 8; value |= (this._buf[this._offset++] & 0xff); } if ((fb & 0x80) == 0x80 && i !== 4) value -= (1 << (i * 8)); return value >> 0; }; var dgram = require("dgram"); function parseTrapPacket(buffer){ var pkt = {}; var reader = new Reader(buffer); reader.readSequence(); pkt.version = reader.readInt();//02 01 00 pkt.community = reader.readString();//04 06 70 75 62 6c 69 63 pkt.type = reader.readSequence();//a4 pkt.enterprise = reader.readOID()//0x06, 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x91, 0x28, 0x02, 0x02, 0x47, 0x64 var bytes = reader.readString(64, true);//0x40, 0x04, 0xc0, 0xa8, 0x17, 0x0a, pkt.agentAddr = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3]; pkt.specific = reader.readInt();// 0x02, 0x01, 0x06, pkt.generic = reader.readInt();//0x02, 0x01, 0x0a pkt.upTime = reader.readTag(67);// pkt.varbinds = readVarbinds(reader); return pkt; }; function readVarbinds (reader) { var vbs = []; reader.readSequence (); while (1) { reader.readSequence(); var oid = reader.readOID (), type = reader.peek (), value = ‘‘; if (type == null) break; switch(type){ case 1: value = reader.readBoolean(); break; case 2: case 65: case 66: case 67: value = reader.readTag(2); break; case 4: value = reader.readString (null); break; case 5: case 128: case 129: case 130: reader.readByte (); reader.readByte (); value = null; break; case 6: value = reader.readOID(); break; case 64: var bytes = reader.readString(64, true); value = bytes.length == 4 ? bytes[0] + ‘.‘ + bytes[1] + ‘.‘ + bytes[2] + ‘.‘ + bytes[3] : ‘‘; break; case 68: case 70: value = reader.readString(type, true); break; } vbs.push ({ oid: oid, type: type, value: value }); } return vbs; } function Receiver(port, onTrap, onError, onStart){ this.port = port; this.socket = null; this.isRunning = false; this.onTrap = onTrap; this.onError = onError; this.onStart = onStart; }; Receiver.prototype.start = function(){ var self = this; if(self.isRunning) return; var socket = self.socket = dgram.createSocket(‘udp4‘); socket.on(‘error‘, function(err){ socket.close(); self.isRunning = false; if(self.onError){ self.onError(err); } }); socket.on(‘message‘, function(msg, remote){ if(self.onTrap){ var pkt = parseTrapPacket(msg); self.onTrap(remote, pkt); } }); socket.on(‘listening‘, function(){ self.isRunning = true; if(self.onStart){ self.onStart(self.port); } }); socket.bind(self.port); }; Receiver.prototype.stop = function(){ var self = this; if(self.isRunning){ if(self.socket){ self.socket.close(); self.isRunning = false; } } }; var trap = new Receiver(162, function(remote, pkt){ console.log(JSON.stringify(remote), JSON.stringify(pkt)); }, ‘‘, function(port){ console.log(‘begin listen on ‘ + port); }); trap.start(); module.exports.TrapReceiver = Receiver;
标签:
原文地址:http://www.cnblogs.com/zh33gl/p/4763197.html