* Progress on parsing/extracting FTN packets
This commit is contained in:
parent
5e55ce4bee
commit
8f33a9a067
|
@ -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) {
|
||||||
|
|
||||||
});
|
});
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue