Skip to content
Snippets Groups Projects
Commit 87d879d9 authored by deuce's avatar deuce
Browse files

Now handles callouts reliably... infinite loop issues fixed.

Still TODO before callout support is "complete":
1) Enhance handling of received file names
   a) On pkt or bundle files, place in sbbsecho inbound directory. with
      a known unique name... don't rely on the remote to make one up.
   b) For req files, handle the file request directly.
   c) All other files, place somewhere else for processing.
2) Perform actions when files are received... touch semaphores, parse TIC, etc.
3) Update flo files after a partial run... mark successful transfers as skip.
4) Put real data into the .try file.
parent 5ace4e05
No related branches found
No related tags found
No related merge requests found
......@@ -10,8 +10,8 @@
* 2) Will not check in a zone-specified directory for the default
* zone. That is, if the default zone is zone 1, and the outbound
* is "/path/to/outbound", it will not correctly handle the case
* where there is a "/path/to/outbound.001" directory. The
* behaviour in this case is undefined and likely to be bad.
* where there is a "/path/to/outbound.001" directory.
* 3) The domain is always 'fidonet'
*
* See FTS-5005 for details.
*/
......@@ -31,7 +31,7 @@ function lock_flow(file, csy)
* Race-safe version...
* 1) If date is "too old", pick a random time in the future.
* 2) Set the file date to that random time.
* 3) Wait one second.
* 3) Wait one second (there's still an unlikely race here)
* 4) If the file date is the random time you chose, set the date
* to now and take "ownership" of the file.
*/
......@@ -91,15 +91,135 @@ function unlock_flow(locks)
}
}
/*
* Given a list of addresses to rescan, calls
* bp.addFile() for any pending file transfers.
*/
function add_outbound_files(addrs, bp)
{
addrs.forEach(function(addr) {
log(LOG_DEBUG, "Adding outbound files for "+addr);
// Find all possible flow files for the remote.
var allfiles = directory(bp.cb_data.binkit_scfg.outbound.replace(/[\\\/]$/)+addr.flo_outbound(bp.default_zone, bp.default_domain)+'*');
// Parse flow files and call addFile() tracking what to do on success.
allfiles.forEach(function(file) {
var flo;
var line;
var action;
var i;
var fnchars = '0123456789abcdefghijklmnopqrstuvwxyz';
var fname;
switch(file_getext(file).toLowerCase()) {
case '.flo':
case '.ilo':
case '.hlo':
case '.clo':
case '.dlo':
flo = new File(file);
if (!flo.open("r")) {
log(LOG_ERROR, "Unable to open FLO file '"+flo.name+"'.");
break;
}
if (bp.cb_data.binkit_flow_contents[flo.name] === undefined)
bp.cb_data.binkit_flow_contents[flo.name] = [];
while((line = flo.readln(2048))) {
switch(line.charAt(0)) {
case '#':
if (bp.addFile(line.substr(1)))
bp.cb_data.binkit_file_actions[flo.name] = 'TRUNCATE';
bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
break;
case '^':
case '-':
if (bp.addFile(line.substr(1)))
bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
break;
case '~':
case '!':
break;
case '@':
line = line.substr(1);
if (bp.addFile(line))
bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
break;
default:
if (bp.addFile(line))
bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
break;
}
}
flo.close();
break;
case '.out':
case '.iut':
case '.hut':
case '.cut':
case '.dut':
fname = '';
for (i=0; i<8; i++)
fname += fnchars[random(fnchars.length)];
fname += '.pkt';
if (bp.addFile(file, fname))
bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
break;
case '.rep':
fname = '';
for (i=0; i<8; i++)
fname += fnchars[random(fnchars.length)];
fname += '.rep';
if (bp.addFile(file, fname))
bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
break;
default:
log(LOG_WARNING, "Unsupported flow file type '"+file+"'.");
break;
}
});
});
}
function callout_auth_cb(mode, bp)
{
/*
* TODO: Add all outgoing mail for all authenticated addresses.
* This is tricky since we need to only use addresses that are
* configured with the single password we sent. The multiple
* password extension (FRL-1013) was withdrawn, so we can't do
* that.
* Loop through remote addresses, building a list of the ones with
* the same password (if we used an empty password, no other nodes
* are allowed)
*/
var addrs = [];
if (bp.cb_data.binkitpw === undefined)
addrs.push(bp.binkit_to_addr);
else {
bp.remote_addrs.forEach(function(addr) {
if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
if (bp.cb_data.binkitcfg.node[addr].pw === bp.cb_data.binkitpw)
addrs.push(addr);
}
else
log(LOG_DEBUG, "Unconfigured address "+addr);
});
}
add_outbound_files(addrs);
}
/*
* Delete completed flo files.
*/
function callout_tx_callback(fname, bp)
{
var j;
Object.keys(bp.bp.cb_data.binkit_flow_contents).forEach(function(flo) {
if (file_exists(flo)) {
while ((j = bp.cb_data.binkit_flow_contents[flo].indexOf(fname)) !== -1)
bp.cb_data.binkit_flow_contents[flo].splice(j, 1);
if (bp.cb_data.binkit_flow_contents[flo].length == 0)
file_remove(flo);
}
});
}
function callout_rx_callback(fname, bp)
......@@ -127,39 +247,82 @@ function callout_want_callback(fobj, fsize, fdate, offset, bp)
return this.file.ACCEPT;
}
function callout_done(bp)
{
var f;
bp.sent_files.forEach(function(file) {
if (bp.cb_data.binkit_file_actions[file] !== undefined) {
switch(bp.cb_data.binkit_file_actions[file]) {
case 'TRUNCATE':
f = new File(file);
if (f.truncate())
log(LOG_INFO, "Truncated '"+f.name+"'.");
else
log(LOG_ERROR, "Unable to truncate '"+f.name+"'.");
break;
case 'DELETE':
if (file_remove(file))
log(LOG_INFO, "Removed '"+file+"'.");
else
log(LOG_ERROR, "Unable to remove '"+file+"'.");
}
}
});
// TODO: update incomplete flow files...
}
function callout(addr, scfg)
{
/*
* TODO: We can force 5D stuff here by adding a "fidonet" argument
* in parse_addr()
*/
var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1);
var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, callout_rx_callback);
var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, callout_rx_callback, callout_tx_callback);
var port;
var f;
log(LOG_INFO, "Callout to "+addr+" started.");
// Force debug mode for now...
bp.cb_data = {
binkitcfg:new BinkITCfg(),
binkit_to_addr:addr,
binkit_scfg:scfg,
binkit_file_actions:{},
binkit_flow_contents:{},
};
if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
bp.cb_data.binkitpw = bp.cb_data.binkitcfg.node[addr].pass;
port = bp.cb_data.binkitcfg.node[addr].port;
bp.require_md5 = !(bp.cb_data.binkitcfg.node[addr].nomd5);
}
// TODO: Force debug mode for now...
bp.debug = true;
bp.default_zone = myaddr.zone;
bp.default_domain = myaddr.domain;
bp.want_callback = callout_want_callback;
bp.rx_callback = callout_rx_callback;
// We won't add files until the auth finishes...
/*
* TODO: We're currently using the packet password... this is not
* only not a good idea, it's a BAD idea since the session password
* is not transmitted in the clear but packet passwords are.
*/
bp.connect(addr, bp.cb_data.binkitpw, callout_auth_cb, port);
callout_done(bp);
// TODO: Some real .try information...
f = new File(bp.cb_data.binkit_scfg.outbound.replace(/[\\\/]$/)+addr.flo_outbound(bp.default_zone, bp.default_domain)+'.try');
if (f.open("w")) {
f.writeln("Callout complete.");
f.close();
}
else {
log(LOG_ERROR, "Unable to create .try file '"+f.name+"'.");
}
}
function run_one_outbound_dir(dir, scfg)
{
var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1);
var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
var flow_files;
var lock_files;
var addr;
var ext;
var i;
var ran = {};
log(LOG_DEBUG, "Running outbound dir "+dir);
......@@ -192,6 +355,8 @@ function run_one_outbound_dir(dir, scfg)
function check_flavour(wildcard, typename)
{
var addr;
while (!js.terminated) {
flow_files = directory(dir+wildcard);
if (flow_files.length == 0)
......@@ -199,12 +364,14 @@ function run_one_outbound_dir(dir, scfg)
flow_file_loop:
for (i=0; i<flow_files.length; i++) {
try {
addr = FIDO.parse_flo_file_path(flow_files[i], myaddr.zone);
addr = FIDO.parse_flo_file_path(flow_files[i], myaddr.zone, 'fidonet');
}
catch(addr_e) {
log(LOG_WARNING, addr_e+" when checking '"+flow_files[i]+"' (default zone: "+myaddr.zone+")");
continue;
}
if (ran[addr] !== undefined)
continue;
ext = file_getext(flow_files[i]);
// Ensure this is the "right" outbound (file case, etc)
......@@ -245,14 +412,8 @@ function run_one_outbound_dir(dir, scfg)
if (i<flow_files.length) {
log(LOG_DEBUG, "Attempting callout for file "+flow_files[i]);
// Use a try/catch to ensure we clean up the lock files.
try {
callout(flow_files[i], scfg);
}
catch(callout_e) {
log(LOG_DEBUG, "Unlocking after exception in callout.");
unlock_flow(lock_files);
throw(callout_e);
}
callout(addr, scfg);
ran[addr] = true;
unlock_flow(lock_files);
}
else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment