Permalink
Browse files

Fixed more issues:

Fixed logic detecting when data is for a channel or a connection.
Fixed when all responses after the first query response contain a rogue field.
Single response queries now work properly field name for value is "res".
   (EG: /ip/address/print =count-only=yes)
Added experimental hexDump feature for debugging.
  • Loading branch information...
1 parent 2519a96 commit 3efedb11a95a049d860a25f3e4e02a55c7cbb797 @Trakkasure committed Jul 7, 2011
Showing with 78 additions and 21 deletions.
  1. +78 −21 lib/index.js
View
@@ -90,8 +90,8 @@ api=function (host,user,password,options) {
return this.handler=new Connection(this);
}
util.inherits(api,events.EventEmitter);
-api.prototype.sentence=function(data) {
- if (this.debug>2) util.debug('Sentence:data: '+data);
+api.prototype.sentence=function(data,more) {
+ if (this.debug>2) util.debug('Sentence:('+more+') data: '+data);
if (this.fatal) { // our last message was a fatal error.
//util.debug('Sentence: fatal error: '+data);
this.packet.push(data);
@@ -113,13 +113,25 @@ api.prototype.sentence=function(data) {
if (this.debug>2) util.debug('Sentence: Sending trap.');
this.handler.emit('trap',e,this.handler);
} else {// no trap. Send general packet.
- //if (this.len||this.datalen) {// we may have a tag.
- if (this.debug>2) util.debug('Sentence: Could have a tag.');
- this.nextTag=1;
+ if (!more) {
+ if (this.debug>2) util.debug('Sentence: No more data in packet. Done.');
+ this.handler.emit('done',this.packet);
+ } else {
+ if (this.debug>2) util.debug('Sentence: Could have a tag.');
+ this.nextTag=1;
+ }
}
//else
//this.handler.emit('done',this.packet,this.handler);
} else
+ if (/=ret=/.test(data)) {
+ if (this.debug>2) util.debug('Sentence: Single return: '+data);
+ this.buffer.push('!re');
+ this.buffer.push(data);
+ this.packet=this.buffer;
+ this.buffer=[];
+ this.nextTag=1; // next could be a tag
+ } else
if (this.nextTag) { // We had a done event, this could be a tag.
this.nextTag=0;
if (data.match(/\.tag/)) {// Check if we have a tag.
@@ -134,11 +146,25 @@ api.prototype.sentence=function(data) {
}
if (this.channel[channel])
this.channel[channel].done(this.packet);
- } else
- if (data.match(/=ret/)) {
- this.nextTag=1;
+ } else {
+ if (/=ret=/.test(data)) {
+ this.nextTag=1;
+ if (this.packet.length) {
+ this.packet.push('!re');
+ this.packet.push(data);
+ } else {
+ this.buffer.push('!re');
+ this.buffer.push(data);
+ this.packet=this.buffer;
+ this.buffer=[];
+ }
+ return;
+ }
+ this.packet=this.buffer;
+ this.buffer=[];
+ this.handler.emit('done',this.packet,this);
+ this.buffer.push(data);
}
- this.buffer.push(data);
} else
if (data.match(/\.tag/)) { // Catch tags where it's not following !done
this.packet=this.buffer; // backup up the packet
@@ -171,44 +197,72 @@ api.prototype.sentence=function(data) {
this.buffer[this.buffer.length]=data;
}
}
+function hexDump(data) {
+ var hex=[]
+ var cref=[];
+ var i=0;
+ for (var j=0;j<data.length;j++) {
+ i=j%8;
+ //m=ctrl.indexOf(data[j]);
+ if (data[j]<20||data[j]>126) cref[i]='.';
+ else cref[i]=String.fromCharCode(data[j])
+ hex[i]=Number(data[j]).toString(16);
+ while (hex[i].length < 2) hex[i] = "0" + hex[i];
+ if (j==8) {
+ console.log(hex.join(' ')+' '+ cref.join('') )
+ hex=[];
+ cref=[];
+ }
+ }
+ if (i!=8) {
+ console.log(hex.join(' ')+' '+ cref.join('') )
+ hex=[];
+ cref=[];
+ }
+}
api.prototype.read=function(data) { // This is the handler for when the socket receives data. Don't call instance function directly
+ if (this.debug>2) {
+ hexDump(data);
+ //util.debug('read: new packet:'+);
+ }
while(data.length) {
if (this.debug>3) util.debug('read: data-len:'+data.length);
if (this.len) { // maintain the current data length. What if the data comes in 2 separate packets?
// I am hopping that the API on the other end doesn't send more than one channel
// at a time if more than one packet is required.
- if (this.debug>3) util.debug('read: len:'+this.len);
//if (this.debug>3) util.debug('read: data:'+data);
if (data.length<=this.len) {
this.len-=data.length;
this.line+=data.toString();
- this.datalen=0;
if (this.debug>3) util.debug('read:consume-all: data:'+data);
if (this.len==0) {
- this.emit('sentence',this.line);
+ this.emit('sentence',this.line,(data.length!=this.len))
this.line='';
}
break;
} else {
- if (this.debug>3) util.debug('read:consume len: data:'+data);
+ if (this.debug>3) util.debug('read:consume len:('+this.len+') data: '+data);
this.line+=data.toString('utf8',0,this.len);
var l=this.line;
this.line='';
data=data.slice(this.len);
- this.datalen=data.length
- this.emit('sentence',l);
var x=decodeLength(data);
this.len=x[1];
data=data.slice(x[0]); // get rid of excess buffer
if (this.len==1&&data[0]=="\x00") {
this.len=0;
- this.data=[];
+ data=data.slice(1); // get rid of excess buffer
}
+ this.emit('sentence',l,data.length);
}
} else {
var x=decodeLength(data);
this.len=x[1];
data=data.slice(x[0]);
+ if (this.len==1&&data[0]=="\x00") {
+ this.len=0;
+ data=data.slice(1); // get rid of excess buffer
+ }
}
}
}
@@ -300,7 +354,7 @@ function Connection(instance) {
if (instance.debug>2) util.debug('Got !done. Need challenge');
return; // waiting for challenge
}
- if (d.match(/=ret=/)) {
+ if (/=ret=/.test(d)) {
if (instance.debug>3)
util.debug('Got challenge');
self.status='Sending Credentials';
@@ -346,7 +400,7 @@ function Connection(instance) {
instance.removeAllListeners('sentence');
self.removeAllListeners('fatal');
self.removeAllListeners('trap');
- instance.addListener('sentence',function(data){instance.sentence(data)});
+ instance.addListener('sentence',function(data,more){instance.sentence(data,more)});
if (instance.debug>2)
util.debug(self.status);
instance.connected=true;
@@ -447,6 +501,7 @@ MikroNode.parseItems=function(data) {
var db=[];
var idx=0;
var record={};
+ //util.puts('parseItems: '+JSON.stringify(data));
data.forEach(function(data){
while(data.length) {
l=data.shift().split(/=/);
@@ -514,7 +569,7 @@ function Channel(instance) {
if (this.closing()) return;
if (d) {
if (typeof(d)=='string')
- d=d.split(/\n/);
+ d=d.split("\n");
if (Array.isArray(d)&&d.length)
this.buffer=this.buffer.concat(d);
else return;
@@ -535,7 +590,7 @@ function Channel(instance) {
if (this.callback)
this.callback(this); // allow setup before sending command.
this.callback=null;
- if (this.getConnection().debug>0) util.debug('Channel ('+this.getConnection().getHost()+":"+this.getId()+') write lines: '+b.join("\n"));
+ if (this.getConnection().debug>0) util.debug('Channel ('+this.getConnection().getHost()+":"+this.getId()+') write lines: '+JSON.stringify(b));
this.getConnection().write(b); // Send command.
}
},
@@ -544,8 +599,10 @@ function Channel(instance) {
util.debug('Channel done: ('+this.getConnection().getHost()+":"+this.getId()+')');
var p=instance.packet;
instance.packet=[];
+ if(!p.length) p=[data];
+ else if(p[p.length-1]!=data) p.push(data);
this.emit('done',p,this);
- if (instance.clearEvents) {
+ if (this.clearEvents()) {
this.removeAllListeners('done');
this.removeAllListeners('data');
this.removeAllListeners('read');

0 comments on commit 3efedb1

Please sign in to comment.