antosdk-apps/Antunnel/build/debug/main.js
2020-08-06 23:45:21 +02:00

493 lines
12 KiB
JavaScript

(function() {
var AntunnelApi, AntunnelService, Msg, Subscriber, W;
Msg = class Msg {
constructor() {
this.header = {
sid: 0,
cid: 0,
type: 0,
size: 0
};
this.data = void 0;
}
as_raw() {
var arr, bytes, length;
length = 21 + this.header.size;
arr = new Uint8Array(length);
arr.set(Msg.MAGIC_START, 0);
arr[4] = this.header.type;
bytes = Msg.bytes_of(this.header.cid);
arr.set(bytes, 5);
bytes = Msg.bytes_of(this.header.sid);
arr.set(bytes, 9);
bytes = Msg.bytes_of(this.header.size);
arr.set(bytes, 13);
if (this.data) {
arr.set(this.data, 17);
}
arr.set(Msg.MAGIC_END, this.header.size + 17);
return arr.buffer;
}
};
Msg.decode = function(raw) {
return new Promise(function(resolve, reject) {
var msg;
msg = new Msg();
if (Msg.int_from(Msg.MAGIC_START, 0) !== Msg.int_from(raw, 0)) {
return reject("Unmatch message begin magic number");
}
msg.header.type = raw[4];
msg.header.cid = Msg.int_from(raw, 5);
msg.header.sid = Msg.int_from(raw, 9);
msg.header.size = Msg.int_from(raw, 13);
msg.data = raw.slice(17, 17 + msg.header.size);
if (Msg.int_from(Msg.MAGIC_END, 0) !== Msg.int_from(raw, 17 + msg.header.size)) {
return reject("Unmatch message end magic number");
}
return resolve(msg);
});
};
Msg.bytes_of = function(x) {
var bytes;
bytes = new Uint8Array(4);
bytes[0] = x & 255;
x = x >> 8;
bytes[1] = x & 255;
x = x >> 8;
bytes[2] = x & 255;
x = x >> 8;
bytes[3] = x & 255;
return bytes;
};
Msg.int_from = function(bytes, offset) {
return bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24);
};
Msg.OK = 0;
Msg.ERROR = 1;
Msg.DATA = 6;
Msg.CLOSE = 5;
Msg.SUBSCRIBE = 2;
Msg.UNSUBSCRIBE = 3;
Msg.CTRL = 7;
Msg.MAGIC_END = [0x41, 0x4e, 0x54, 0x44];
Msg.MAGIC_START = [0x44, 0x54, 0x4e, 0x41];
Subscriber = class Subscriber {
constructor(channel) {
this.channel = channel;
this.id = void 0;
this.channel_id = void 0;
this.onmessage = void 0;
this.onerror = void 0;
this.onopen = void 0;
this.onclose = void 0;
this.tunnel = void 0;
this.is_opened = false;
}
send(type, arr) {
if (!this.tunnel) {
if (this.onerror) {
this.onerror("Tunnel is not opened");
}
return;
}
if (!this.is_opened) {
if (this.onerror) {
this.onerror("Channel is not opened yet");
}
return;
}
return this.tunnel.send(this.genmsg(type, arr));
}
genmsg(type, data) {
var msg;
msg = new Msg();
msg.header.sid = this.id;
msg.header.cid = this.channel_id;
msg.header.type = type;
msg.header.size = data ? data.length : 0;
msg.data = data;
return msg;
}
close(b) {
this.is_opened = false;
if (!this.tunnel) {
return;
}
return this.tunnel.unsubscribe(this, b);
}
};
AntunnelApi = class AntunnelApi {
constructor(uri1) {
this.uri = uri1;
this.socket = void 0;
this.pending = {};
this.subscribers = {};
this.onclose = void 0;
}
ready() {
return new Promise((resolve, reject) => {
if (!this.uri) {
return reject();
}
if (this.socket !== void 0) {
return resolve();
}
// connect to the socket
console.log(`Connect to ${this.uri}`);
this.socket = new WebSocket(this.uri);
this.socket.binaryType = 'arraybuffer';
this.socket.onmessage = (evt) => {
return this.process(evt);
};
this.socket.onclose = (evt) => {
var k, ref, ref1, v;
this.socket = void 0;
ref = this.pending;
for (k in ref) {
v = ref[k];
v.tunnel = void 0;
if (v.onclose) {
v.onclose();
}
}
ref1 = this.subscribers;
for (k in ref1) {
v = ref1[k];
v.tunnel = void 0;
v.is_opened = false;
if (v.onclose) {
v.onclose();
}
}
this.pending = {};
this.subscribe = {};
if (this.onclose()) {
return this.onclose();
}
};
this.socket.onerror = (evt) => {
var k, ref, ref1, results, v;
ref = this.pending;
for (k in ref) {
v = ref[k];
if (v.onerror) {
v.onerror(evt.toString());
}
}
ref1 = this.subscribers;
results = [];
for (k in ref1) {
v = ref1[k];
if (v.onerror) {
results.push(v.onerror(evt.toString()));
}
}
return results;
};
return this.socket.onopen = (e) => {
return resolve();
};
});
}
process(evt) {
return Msg.decode(new Uint8Array(evt.data)).then((msg) => {
var relay_msg, sub;
// find the correct subscriber of the data
relay_msg = (m, a) => {
var sub;
sub = this.pending[m.header.sid];
if (sub) {
if (sub[a]) {
sub[a](m);
}
return;
}
sub = this.subscribers[m.header.sid];
if (sub) {
if (sub[a]) {
return sub[a](m);
}
}
};
switch (msg.header.type) {
case Msg.OK:
// first look for the pending
sub = this.pending[msg.header.sid];
if (sub) {
delete this.pending[msg.header.sid];
sub.id = Msg.int_from(msg.data, 0);
sub.channel_id = msg.header.cid;
this.subscribers[sub.id] = sub;
sub.is_opened = true;
if (sub.onopen) {
return sub.onopen();
}
} else {
return relay_msg(msg, "onmessage");
}
break;
case Msg.DATA:
return relay_msg(msg, "onmessage");
case Msg.ERROR:
return relay_msg(msg, "onerror");
case Msg.UNSUBSCRIBE:
sub = this.subscribers[msg.header.sid];
if (!sub) {
return;
}
return sub.close(true);
default:
return console.error(`Message of type ${msg.header.type} is unsupported`, msg);
}
}).catch((e) => {
var k, ref, ref1, results, v;
ref = this.pending;
for (k in ref) {
v = ref[k];
if (v.onerror) {
v.onerror(e);
}
}
ref1 = this.subscribers;
results = [];
for (k in ref1) {
v = ref1[k];
if (v.onerror) {
results.push(v.onerror(e));
}
}
return results;
});
}
subscribe(sub) {
return this.ready().then(() => {
// insert it to pending list
sub.tunnel = this;
sub.id = Math.floor(Math.random() * 100000) + 1;
while (this.subscribers[sub.id] || this.pending[sub.id]) {
sub.id = Math.floor(Math.random() * 100000) + 1;
}
this.pending[sub.id] = sub;
// send request to connect to a channel
return this.send(sub.genmsg(Msg.SUBSCRIBE, (new TextEncoder()).encode(sub.channel)));
}).catch(function(e) {
if (sub.onerror) {
return sub.onerror(e.toString());
}
});
}
unsubscribe(sub, b) {
return this.ready().then(() => {
if (!this.subscribers[sub.id]) {
return;
}
if (!b) {
// insert it to pending list
// send request to connect to a channel
this.send(sub.genmsg(Msg.UNSUBSCRIBE, void 0));
}
if (sub.onclose) {
sub.onclose();
}
delete this.subscribers[sub.id];
sub.tunnel = void 0;
return sub.is_opened = false;
}).catch(function(e) {
if (sub.onerror) {
return sub.onerror(e.toString());
}
});
}
send(msg) {
// return unless @subscribers[msg.header.sid]
return this.socket.send(msg.as_raw());
}
close() {
console.log(`Close connection to ${this.uri}`);
if (this.socket) {
this.socket.close();
}
if (this.onclose()) {
return this.onclose();
}
}
};
W = this;
W.Antunnel = {
tunnel: void 0,
init: (function(url) {
return new Promise(function(resolve, reject) {
if (W.Antunnel.tunnel) {
return resolve(W.Antunnel.tunnel);
}
W.Antunnel.tunnel = new AntunnelApi(url);
W.Antunnel.tunnel.onclose = function() {
return W.Antunnel.tunnel = void 0;
};
return W.Antunnel.tunnel.ready().then(function() {
return resolve(W.Antunnel.tunnel);
}).catch(function(e) {
return reject(e);
});
});
}),
Subscriber: Subscriber,
Msg: Msg
};
AntunnelService = class AntunnelService extends OS.application.BaseService {
constructor(args) {
super("AntunnelService", args);
this.text = __("Tunnel");
this.iconclass = "fa fa-close";
this.is_connect = false;
this.nodes = [
{
text: __("Connect"),
id: 1
},
{
text: __("Disconnect"),
id: 2
},
{
text: __("Enter uri"),
id: 3
},
{
text: __("Exit"),
id: 4
}
];
this.onchildselect = (e) => {
return this.action(e);
};
}
init() {
if (this.systemsetting.system.tunnel_uri) {
this.start();
}
this.watch(1500, () => {
var new_status;
new_status = false;
if (Antunnel.tunnel !== void 0) {
new_status = true;
}
if (new_status === this.is_connect) {
return;
}
this.is_connect = new_status;
this.iconclass = "fa fa-circle";
if (!this.is_connect) {
this.iconclass = "fa fa-close";
}
return this.update();
});
return OS.onexit("cleanupAntunnel", () => {
if (Antunnel.tunnel) {
Antunnel.tunnel.close();
}
return this.quit();
});
}
action(e) {
var ask;
ask = () => {
return this._gui.openDialog("PromptDialog", {
title: __("Tunnel uri"),
label: __("Please enter tunnel uri"),
value: "wss://localhost/tunnel"
}).then((uri) => {
if (!(uri && uri !== "")) {
return;
}
this.systemsetting.system.tunnel_uri = uri;
return this.start();
});
};
switch (e.data.item.data.id) {
case 1:
if (this.is_connect) {
return;
}
if (this.systemsetting.system.tunnel_uri) {
return this.start();
} else {
return ask();
}
break;
case 2:
if (Antunnel.tunnel) {
return Antunnel.tunnel.close();
}
break;
case 3:
if (Antunnel.tunnel) {
Antunnel.tunnel.close();
}
return ask();
case 4:
if (Antunnel.tunnel) {
Antunnel.tunnel.close();
}
return this.quit();
}
}
start() {
if (!this.systemsetting.system.tunnel_uri) {
return;
}
if (Antunnel.tunnel) {
return;
}
return Antunnel.init(this.systemsetting.system.tunnel_uri).then((t) => {
return this.notify(__("Tunnel now connected to the server at: {0}", this.systemsetting.system.tunnel_uri));
}).catch((e) => {
if (Antunnel.tunnel) {
Antunnel.tunnel.close();
}
return this.error(__("Unable to connect to the tunnel: {0}", e.toString()), e);
});
}
awake() {}
};
this.OS.register("AntunnelService", AntunnelService);
}).call(this);