* Progress on parsing/extracting FTN packets

This commit is contained in:
Bryan Ashby 2015-07-14 17:08:52 -06:00
parent 5e55ce4bee
commit 8f33a9a067
2 changed files with 136 additions and 25 deletions

View File

@ -53,7 +53,7 @@ function FTNMailPacket(options) {
}; };
}; };
this.getNetworkForAddress = function(addr) { this.getNetworkNameForAddress = function(addr) {
var nodeAddr; var nodeAddr;
for(var network in self.nodeAddresses) { for(var network in self.nodeAddresses) {
nodeAddr = self.nodeAddresses[network]; nodeAddr = self.nodeAddresses[network];
@ -67,7 +67,7 @@ function FTNMailPacket(options) {
} }
}; };
this.loadPacketHeader = function(packetBuffer, cb) { this.parseFtnPacketHeader = function(packetBuffer, cb) {
assert(Buffer.isBuffer(packetBuffer)); assert(Buffer.isBuffer(packetBuffer));
if(packetBuffer.length < 58) { if(packetBuffer.length < 58) {
@ -93,7 +93,7 @@ function FTNMailPacket(options) {
.buffer('password', 8) // null terminated C style string .buffer('password', 8) // null terminated C style string
.word16lu('origZone') .word16lu('origZone')
.word16lu('destZone') .word16lu('destZone')
// where is the rest of the spec? // :TODO: Document the various specs/fields more
.word16lu('auxNet') .word16lu('auxNet')
.word16lu('capWordA') .word16lu('capWordA')
.word8('prodCodeHi') .word8('prodCodeHi')
@ -107,37 +107,131 @@ function FTNMailPacket(options) {
.tap(function tapped(packetHeader) { .tap(function tapped(packetHeader) {
packetHeader.password = ftn.stringFromFTN(packetHeader.password); packetHeader.password = ftn.stringFromFTN(packetHeader.password);
// :TODO: Don't hard code magic # here
if(2 !== packetHeader.packetType) {
cb(new Error('Packet is not Type-2'));
return;
}
// :TODO: validate & pass error if failure
cb(null, packetHeader); cb(null, packetHeader);
}); });
}; };
this.loadMessagesFromPacketBuffer = function(packetBuffer, cb) { this.parseFtnMessageBody = function(msgBodyBuffer, cb) {
async.series(
};
this.parseFtnMessages = function(buffer, cb) {
var nullTermBuf = new Buffer( [ 0 ] );
var fidoMessages = [];
binary.stream(buffer).loop(function looper(end, vars) {
this
.word16lu('messageType')
.word16lu('originNode')
.word16lu('destNode')
.word16lu('originNet')
.word16lu('destNet')
.word8('attrFlags1')
.word8('attrFlags2')
.word16lu('cost')
.scan('modDateTime', nullTermBuf)
.scan('toUserName', nullTermBuf)
.scan('fromUserName', nullTermBuf)
.scan('subject', nullTermBuf)
.scan('message', nullTermBuf)
.tap(function tapped(msgData) {
if(!msgData.originNode) {
end();
cb(null, fidoMessages);
return;
}
// buffer to string conversion
// :TODO: What is the real encoding here?
[ 'modDateTime', 'toUserName', 'fromUserName', 'subject', ].forEach(function field(f) {
msgData[f] = msgData[f].toString();
});
fidoMessages.push(_.clone(msgData));
});
});
};
/*
this.loadMessageHeader = function(msgHeaderBuffer, cb) {
assert(Buffer.isBuffer(msgHeaderBuffer));
if(msgHeaderBuffer.length < 14) {
cb(new Error('Buffer too small'));
return;
}
binary.parse(msgHeaderBuffer)
.word16lu('messageType')
.word16lu('originNode')
.word16lu('destNode')
.word16lu('originNet')
.word16lu('destNet')
.word8('attrFlags1')
.word8('attrFlags2')
.word16lu('cost')
.tap(function tapped(msgHeader) {
console.log(msgHeader)
var nullTermBuf = new Buffer( [ 0 ] );
var offset = 14;
binary.parse(msgHeaderBuffer.slice(offset))
.scan('modDateTime', nullTermBuf)
.scan('toUserName', nullTermBuf)
.tap(function tapped(varMsgHeader) {
console.log(varMsgHeader.modDateTime.toString())
console.log(varMsgHeader.toUserName.toString())
});
cb(null, msgHeader);
});
};
this.loadMessage = function(buf, cb) {
var bufPosition = 0;
async.waterfall(
[ [
function loadHdr(callback) { function loadHdr(callback) {
self.loadPacketHeader(packetBuffer, function headerLoaded(err, packetHeader) { self.loadMessageHeader(buf.slice(bufPosition), function headerLoaded(err, msgHeader) {
callback(err, msgHeader);
});
}
]
);
};
*/
this.loadMessagesFromPacketBuffer = function(packetBuffer, cb) {
async.waterfall(
[
function parseHeader(callback) {
self.parseFtnPacketHeader(packetBuffer, function headerParsed(err, packetHeader) {
self.packetHeader = packetHeader; self.packetHeader = packetHeader;
callback(err); callback(err);
}); });
}, },
function validateType(callback) { function validateDesinationAddress(callback) {
// :TODO: don't use a magic # here.... self.localNetworkName = self.getNetworkNameForAddress(self.getPacketHeaderAddress());
if(2 !== self.packetHeader.packetType) { callback(self.localNetworkName ? null : new Error('Packet not addressed do this system'));
callback(new Error('Packet is not Type-2'));
} else {
callback(null);
}
}, },
function checkAddress(callback) { function parseMessages(callback) {
/* self.parseFtnMessages(packetBuffer.slice(58), function messagesParsed(err, fidoMessages) {
if(0 !== self.packetHeader.destPoint) { callback(err, fidoMessages);
self.packetNodeAddress = ftn.getFormattedFTNAddress(self.getPacketHeaderAddress(), '4D'); });
} else { },
self.packetNodeAddress = ftn.getFormattedFTNAddress(self.getPacketHeaderAddress(), '3D'); function createMessageObjects(fidoMessages, callback) {
}*/ fidoMessages.forEach(function msg(fmsg) {
console.log(fmsg.subject);
var network = self.getNetworkForAddress(self.getPacketHeaderAddress()); });
callback(network ? null : new Error('Packet not addressed do this system'));
} }
], ],
function complete(err) { function complete(err) {
@ -185,6 +279,6 @@ var mailPacket = new FTNMailPacket(
} }
); );
mailPacket.parse('/home/nuskooler/ownCloud/Projects/ENiGMA½ BBS/FTNPackets/27000425.pkt', function parsed(err, messages) { mailPacket.parse('/home/bashby/ownCloud/Projects/ENiGMA½ BBS/FTNPackets/27000425.pkt', function parsed(err, messages) {
}); });

View File

@ -13,6 +13,8 @@ var util = require('util');
exports.stringFromFTN = stringFromFTN; exports.stringFromFTN = stringFromFTN;
exports.getFormattedFTNAddress = getFormattedFTNAddress; exports.getFormattedFTNAddress = getFormattedFTNAddress;
// See list here: https://github.com/Mithgol/node-fidonet-jam
function stringFromFTN(buf, encoding) { function stringFromFTN(buf, encoding) {
var nullPos = buf.length; var nullPos = buf.length;
@ -67,7 +69,7 @@ function getFormattedFTNAddress(address, dimensions) {
return addr; return addr;
} }
function getFTNMessageSerialNumber(messageId) { function getFtnMessageSerialNumber(messageId) {
return ((Math.floor((Date.now() - Date.UTC(2015, 1, 1)) / 1000) + messageId)).toString(16); return ((Math.floor((Date.now() - Date.UTC(2015, 1, 1)) / 1000) + messageId)).toString(16);
} }
@ -75,6 +77,21 @@ function getFTNMessageID(messageId, areaId) {
return messageId + '.' + areaId + '@' + getFTNAddress() + ' ' + getFTNMessageSerialNumber(messageId) return messageId + '.' + areaId + '@' + getFTNAddress() + ' ' + getFTNMessageSerialNumber(messageId)
} }
//
// Specs:
// * http://ftsc.org/docs/fts-0009.001
// *
//
function getFtnMsgIdKludgeLine(origAddress, messageId) {
if(_.isObject(origAddress)) {
origAddress = getFormattedFTNAddress(origAddress, '5D');
}
return '\x01MSGID: ' + origAddress + ' ' + getFtnMessageSerialNumber(messageId);
}
function getFTNOriginLine() { function getFTNOriginLine() {
// //
// Specs: // Specs: