zoukankan      html  css  js  c++  java
  • nodejs实现接收Snmp的Trap消息

    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;
    

      

  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/zh33gl/p/4763197.html
Copyright © 2011-2022 走看看