add new package

This commit is contained in:
lxsang
2020-08-06 23:21:42 +02:00
parent 694afc162d
commit 525badca3f
28 changed files with 1099 additions and 2 deletions

5
Antunnel/README.md Normal file
View File

@ -0,0 +1,5 @@
# Antunnel
`Antunnel` is a client side API that allows AntOS applications to
talk to server side applications via the [`antd-tunnel-pligin`](https://github.com/lxsang/antd-tunnel-plugin) plugin
using a single websocket API.

View File

@ -0,0 +1,5 @@
# Antunnel
`Antunnel` is a client side API that allows AntOS applications to
talk to server side applications via the [`antd-tunnel-pligin`](https://github.com/lxsang/antd-tunnel-plugin) plugin
using a single websocket API.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
{
"pkgname": "Antunnel",
"name":"Antunnel",
"services": [
"AntunnelService"
],
"description":"Antunnel API library",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@lxsang.me"
},
"version":"0.1.1-a",
"category":"Library",
"iconclass":"fa fa-adn",
"mimes":["none"],
"locale": {}
}

View File

@ -0,0 +1,5 @@
<afx-app-window apptitle="Antunnel" width="500" height="400" data-id="Antunnel">
<afx-hbox >
<afx-button text="Sub" data-id="btsub"></afx-button>
</afx-hbox>
</afx-app-window>

Binary file not shown.

View File

@ -0,0 +1,232 @@
class Msg
constructor: () ->
@header = {
sid: 0,
cid: 0,
type: 0,
size: 0
}
@data = undefined
as_raw:() ->
length = 21 + @header.size
arr = new Uint8Array(length)
arr.set(Msg.MAGIC_START, 0)
arr[4] = @header.type
bytes = Msg.bytes_of @header.cid
arr.set(bytes,5)
bytes = Msg.bytes_of @header.sid
arr.set(bytes,9)
bytes = Msg.bytes_of @header.size
arr.set(bytes,13)
if @data
arr.set(@data, 17)
arr.set(Msg.MAGIC_END, @header.size + 17)
arr.buffer
Msg.decode = (raw) ->
new Promise (resolve, reject) ->
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")
resolve msg
Msg.bytes_of = (x) ->
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)
bytes
Msg.int_from = (bytes, offset) ->
(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 ]
class Subscriber
constructor: (@channel) ->
@id = undefined
@channel_id = undefined
@onmessage = undefined
@onerror = undefined
@onopen = undefined
@onclose = undefined
@tunnel = undefined
@is_opened = false
send: (type, arr) ->
if not @tunnel
@onerror "Tunnel is not opened" if @onerror
return
if not @is_opened
@onerror "Channel is not opened yet" if @onerror
return
@tunnel.send @genmsg type, arr
genmsg: (type, data) ->
msg = new Msg()
msg.header.sid = @id
msg.header.cid = @channel_id
msg.header.type = type
msg.header.size = if data then data.length else 0
msg.data = data
msg
close: (b) ->
@is_opened = false
return unless @tunnel
@tunnel.unsubscribe @, b
class AntunnelApi
constructor: (@uri) ->
@socket = undefined
@pending = {}
@subscribers = {}
@onclose = undefined
ready: () ->
return new Promise (resolve, reject) =>
return reject() if not @uri
return resolve() if @socket isnt undefined
# connect to the socket
console.log "Connect to #{@uri}"
@socket = new WebSocket(@uri)
@socket.binaryType = 'arraybuffer'
@socket.onmessage = (evt) => @process evt
@socket.onclose = (evt) =>
@socket = undefined
for k,v of @pending
v.tunnel = undefined
v.onclose() if v.onclose
for k,v of @subscribers
v.tunnel = undefined
v.is_opened = false
v.onclose() if v.onclose
@pending = {}
@subscribe = {}
@onclose() if @onclose()
@socket.onerror = (evt) =>
v.onerror(evt.toString()) for k,v of @pending when v.onerror
v.onerror(evt.toString()) for k,v of @subscribers when v.onerror
@socket.onopen = (e) => resolve()
process: (evt) ->
Msg.decode(new Uint8Array(evt.data)).then (msg) =>
# find the correct subscriber of the data
relay_msg = (m, a) =>
sub = @pending[m.header.sid]
if sub
sub[a] m if sub[a]
return
sub = @subscribers[m.header.sid]
if sub
sub[a] m if sub[a]
switch msg.header.type
when Msg.OK
# first look for the pending
sub = @pending[msg.header.sid]
if sub
delete @pending[msg.header.sid]
sub.id = Msg.int_from(msg.data,0)
sub.channel_id = msg.header.cid
@subscribers[sub.id] = sub
sub.is_opened = true
sub.onopen() if sub.onopen
else
relay_msg msg, "onmessage"
when Msg.DATA
relay_msg msg, "onmessage"
when Msg.ERROR
relay_msg msg, "onerror"
when Msg.UNSUBSCRIBE
sub = @subscribers[msg.header.sid]
return unless sub
sub.close(true)
else
console.error "Message of type #{msg.header.type} is unsupported", msg
.catch (e) =>
v.onerror(e) for k,v of @pending when v.onerror
v.onerror(e) for k,v of @subscribers when v.onerror
subscribe: (sub) ->
@ready().then ()=>
# insert it to pending list
sub.tunnel = @
sub.id = Math.floor(Math.random()*100000) + 1
while @subscribers[sub.id] or @pending[sub.id]
sub.id = Math.floor(Math.random()*100000) + 1
@pending[sub.id] = sub
# send request to connect to a channel
@send sub.genmsg Msg.SUBSCRIBE, (new TextEncoder()).encode(sub.channel)
.catch (e) ->
sub.onerror e.toString() if sub.onerror
unsubscribe: (sub, b) ->
@ready().then ()=>
return unless @subscribers[sub.id]
# insert it to pending list
# send request to connect to a channel
@send sub.genmsg Msg.UNSUBSCRIBE, undefined if not b
sub.onclose() if sub.onclose
delete @subscribers[sub.id]
sub.tunnel = undefined
sub.is_opened = false
.catch (e) ->
sub.onerror e.toString() if sub.onerror
send: (msg) ->
# return unless @subscribers[msg.header.sid]
@socket.send msg.as_raw()
close: () ->
console.log "Close connection to #{@uri}"
@socket.close() if @socket
@onclose() if @onclose()
W = this
W.Antunnel = {
tunnel: undefined
init: ((url) ->
return new Promise (resolve, reject) ->
return resolve(W.Antunnel.tunnel) if W.Antunnel.tunnel
W.Antunnel.tunnel = new AntunnelApi(url)
W.Antunnel.tunnel.onclose = () -> W.Antunnel.tunnel = undefined
W.Antunnel.tunnel.ready().then () ->
resolve(W.Antunnel.tunnel)
.catch (e) -> reject(e)),
Subscriber: Subscriber,
Msg: Msg
}

View File

@ -0,0 +1,68 @@
class AntunnelService extends OS.application.BaseService
constructor: (args) ->
super "AntunnelService", args
@text = __("Tunnel")
@iconclass = "fa fa-close"
@is_connect = false
@nodes = [
{text: __("Connect"), id: 1},
{text: __("Disconnect"), id: 2},
{text: __("Enter uri"), id: 3},
{text: __("Exit"), id: 4}
]
@onchildselect = (e) => @action e
init: () ->
@start() if @systemsetting.system.tunnel_uri
@watch 1500, () =>
new_status = false
new_status = true if Antunnel.tunnel isnt undefined
return unless new_status isnt @is_connect
@is_connect = new_status
@iconclass = "fa fa-circle"
@iconclass = "fa fa-close" unless @is_connect
@update()
action: (e) ->
ask = () =>
@_gui.openDialog("PromptDialog", {
title: __("Tunnel uri"),
label: __("Please enter tunnel uri"),
value: "wss://localhost/tunnel"
})
.then (uri) =>
return unless uri and uri isnt ""
@systemsetting.system.tunnel_uri = uri
@start()
switch e.data.item.data.id
when 1
return if @is_connect
if @systemsetting.system.tunnel_uri
@start()
else
ask()
when 2
Antunnel.tunnel.close() if Antunnel.tunnel
when 3
Antunnel.tunnel.close() if Antunnel.tunnel
ask()
when 4
Antunnel.tunnel.close() if Antunnel.tunnel
@quit()
start: () ->
return unless @systemsetting.system.tunnel_uri
return if Antunnel.tunnel
Antunnel.init(@systemsetting.system.tunnel_uri).then (t) =>
@notify __("Tunnel now connected to the server at: {0}", @systemsetting.system.tunnel_uri)
.catch (e) =>
Antunnel.tunnel.close() if Antunnel.tunnel
@error __("Unable to connect to the tunnel: {0}", e.toString()), e
awake: () ->
this.OS.register "AntunnelService", AntunnelService

17
Antunnel/package.json Normal file
View File

@ -0,0 +1,17 @@
{
"pkgname": "Antunnel",
"name":"Antunnel",
"services": [
"AntunnelService"
],
"description":"Antunnel API library",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@lxsang.me"
},
"version":"0.1.1-a",
"category":"Library",
"iconclass":"fa fa-adn",
"mimes":["none"],
"locale": {}
}

8
Antunnel/project.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "Antunnel",
"root": "home://workspace/antosdk-apps/Antunnel",
"css": [],
"javascripts": [],
"coffees": ["coffees/Antunnel.coffee", "coffees/AntunnelService.coffee"],
"copies": ["package.json", "README.md"]
}