From 139de2c6bde467972e3303d850552e14400f20eb Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Wed, 13 Jan 2016 04:44:33 +0000
Subject: [PATCH] Start of BinkP implementation in JavaScript.

---
 exec/load/binkp.js | 239 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 239 insertions(+)
 create mode 100644 exec/load/binkp.js

diff --git a/exec/load/binkp.js b/exec/load/binkp.js
new file mode 100644
index 0000000000..e86bfab601
--- /dev/null
+++ b/exec/load/binkp.js
@@ -0,0 +1,239 @@
+load("sockdefs.js");
+
+function BinkP()
+{
+	var addr;
+
+	this.default_zone = 1;
+	addr = this.parse_addr(system.fido_addr_list[0]);
+	if (addr.zone !== undefined)
+		this.default_zone = addr.zone;
+	this.sock  = undefined;
+	this.senteob = false;
+	this.goteob = false;
+	this.pending_ack = {};
+	this.pending_get = {};
+	this.debug = false
+}
+BinkP.prototype.Frame = function() {}
+BinkP.prototype.command = {
+	M_NUL:0,
+	M_ADR:1,
+	M_PWD:2,
+	M_FILE:3,
+	M_OK:4,
+	M_EOB:5,
+	M_GOT:6,
+	M_ERR:7,
+	M_BSY:8,
+	M_GET:9,
+	M_SKIP:10,
+}
+BinkP.prototype.command_name = [
+	"M_NUL",
+	"M_ADR",
+	"M_PWD",
+	"M_FILE",
+	"M_OK",
+	"M_EOB",
+	"M_GOT",
+	"M_ERR",
+	"M_BSY",
+	"M_GET",
+	"M_SKIP"
+];
+BinkP.prototype.parse_addr = function(addr)
+{
+	var m;
+	var ret={};
+
+	m = addr.match(/^([0-9]+):/);
+	if (m !== null)
+		ret.zone = parseInt(m[1], 10);
+	else
+		ret.zone = this.default_zone;
+
+	m = addr.match(/([0-9]+)\//);
+	if (m !== null)
+		ret.net = parseInt(m[1], 10);
+
+	m = addr.match(/\/([0-9]+)/);
+	if (m !== null)
+		ret.node = parseInt(m[1], 10);
+
+	m = addr.match(/\.([0-9]+)/);
+	if (m !== null)
+		ret.point = parseInt(m[1], 10);
+
+	m = addr.match(/@.+$/);
+	if (m !== null)
+		ret.domain = m[1];
+
+	return ret;
+}
+BinkP.prototype.faddr_to_inetaddr = function(addr)
+{
+	var ret = '';
+	if (addr.point !== undefined && addr.point !== 0)
+		ret += format("p%d", addr.point);
+	ret += format("f%d.n%d.z%d.binkp.net", addr.node, addr.net, addr.zone);
+	return ret;
+}
+BinkP.prototype.connect = function(addr, password, port)
+{
+	var i;
+	var pkt;
+
+	if (addr === undefined)
+		throw("No password specified!");
+	addr = this.parse_addr(addr);
+	if (addr.net === undefined || addr.node == undefined)
+		return false;
+
+	if (password === undefined)
+		password = '-';
+
+	if (port === undefined)
+		port = 24554;
+
+	if (this.sock === undefined)
+		this.sock = new Socket(SOCK_STREAM, "binkp");
+
+	if(!this.sock.connect(this.faddr_to_inetaddr(addr), port))
+		return false;
+
+	this.sendCmd(this.command.M_NUL, "SYS "+system.name);
+	this.sendCmd(this.command.M_NUL, "ZYZ "+system.operator);
+	this.sendCmd(this.command.M_NUL, "LOC "+system.location);
+	this.sendCmd(this.command.M_NUL, "NDL 115200,TCP,BINKP");
+	this.sendCmd(this.command.M_NUL, "TIME "+system.timestr());
+	this.sendCmd(this.command.M_NUL, "VER JSBinkP/0.0.0/"+system.platform+" binkp/1.0");
+	for (i=0; i<system.fido_addr_list.length; i++)
+		this.sendCmd(this.command.M_ADR, system.fido_addr_list[i]);
+	this.sendCmd(this.command.M_PWD, password);
+	while(!js.terminated) {
+		pkt = this.recvFrame();
+		if (pkt === undefined)
+			return false;
+		if (pkt.is_cmd) {
+			if (pkt.command == this.command.M_OK)
+				break;
+		}
+	}
+	if (js.termianted) {
+		this.close();
+		return false;
+	}
+	return true;
+}
+BinkP.prototype.close = function()
+{
+	// Send an ERR and close.
+	if ((!this.goteob) || Object.keys(this.pending_ack).length || Object.keys(this.pending_get).length) {
+		this.sendCmd(this.command.M_ERR, "Forced Shutdown");
+	}
+	else {
+		if (!this.senteob) {
+			this.sendCmd(this.command.M_EOB, "");
+		}
+	}
+}
+BinkP.prototype.sendCmd = function(cmd, data)
+{
+	var type;
+
+	if (data === undefined)
+		data = '';
+	if (this.debug) {
+		if (cmd < this.command_name.length)
+			type = this.command_name[cmd];
+		else
+			type = 'Unknown Command '+cmd;
+		log(LOG_DEBUG, "Sent "+type+" command args: "+data);
+	}
+	var len = data.length+1;
+	len |= 0x8000;
+	this.sock.sendBin(len, 2)
+	this.sock.sendBin(cmd, 1)
+	this.sock.send(data);
+	if (cmd === this.command.M_EOB)
+		this.senteob = true;
+	if (cmd === this.command.M_ERR || cmd === this.command.M_BSY) {
+		this.sock.close();
+		this.socket = undefined;
+	}
+	return true;
+}
+BinkP.prototype.sendData = function(data)
+{
+	var len = data.length;
+	if (this.debug)
+		log(LOG_DEBUG, "Sending "+data.length+" bytes of data");
+	this.sock.sendBin(len, 2)
+	this.sock.send(data);
+}
+BinkP.prototype.recvFrame = function()
+{
+	var ret = new this.Frame();
+	var type;
+
+	ret.length = this.sock.recvBin(2)
+	ret.is_cmd = (ret.length & 0x8000) ? true : false;
+	ret.length &= 0x7fff;
+	if (ret.length == 0)
+		ret.data = '';
+	else
+		ret.data = this.sock.recv(ret.length);
+	if (ret.is_cmd) {
+		ret.command = ret.data.charCodeAt(0);
+		ret.data = ret.data.substr(1);
+	}
+	if (this.debug) {
+		if (ret.is_cmd) {
+			if (ret.command < this.command_name.length)
+				type = this.command_name[ret.command];
+			else
+				type = 'Unknown Command '+ret.command;
+			log(LOG_DEBUG, "Got "+type+" command args: "+ret.data);
+		}
+		else
+			log(LOG_DEBUG, "Got data frame length "+ret.length);
+	}
+	if (ret.is_cmd) {
+		if (ret.command === this.command.M_ERR) {
+			log(LOG_ERROR, "BinkP got fatal error from remote: '"+ret.data+"'.");
+			this.sock.close();
+			this.socket = undefined;
+			return undefined;
+		}
+		if (ret.command === this.command.M_BSY) {
+			log(LOG_WARNING, "BinkP got non-fatal error from remote: '"+ret.data+"'.");
+			this.sock.close();
+			this.socket = undefined;
+			return undefined;
+		}
+		if (ret.command == this.command.M_EOB)
+			this.goteob = true;
+	}
+	return ret;
+}
+BinkP.prototype.skipFiles = function()
+{
+	var pkt;
+
+	while(!(js.terminated || this.goteob)) {
+		pkt = this.recvFrame();
+		if (pkt === undefined)
+			return false;
+		if (pkt.is_cmd) {
+			if (pkt.command == this.command.M_EOB)
+				return true;
+			if (pkt.command == this.command.M_FILE || pkt.command == this.command.M_GET) {
+				this.sendCmd(this.command.M_SKIP, pkt.data.replace(/ [0-9]+$/,''));
+			}
+		}
+	}
+	if (js.terminated)
+		this.close();
+	return true;
+}
-- 
GitLab