export function direct_plugin({p2p, hello}={}) :: hello = hello || 'mc' let _direct_ = @{} connect(peer, channel_id) :: return this.connectPair(peer, channel_id)[0] pair(peer, channel_id) :: return Promise.all @ this.connectPair(peer, channel_id) connectPair(peer, channel_id) :: let [recv_peer, chan_peer] = (peer.direct || peer).createDirect @ pkt => recv_self(pkt), channel_id let [recv_self, chan_self] = this.createDirect @ recv_peer, channel_id return @[] chan_self, chan_peer mc_connect(opt, tgt1, tgt2) :: if 'string' === typeof opt :: opt = {client_id: opt} let mc = new MessageChannel() tgt1.postMessage @ {hello, mc_port: mc.port1, ...opt}, [mc.port1] if tgt2 && tgt2.postMessage :: tgt2.postMessage @ {hello, mc_port: mc.port2, ...opt}, [mc.port2] else :: return this.connectMsgPort @ mc.port2, tgt2 mc_server(host, options={}) :: let id_pre = options.channel_id || 'mcsv-' let subscribe = options.subscribe || _on_msg_evt subscribe @ host, (data, evt) => :: if data && hello == data.hello :: if evt :: evt.stopPropagation() let chan = this.connectMsgPort @ data.mc_port || evt.ports[0], @{} ... options channel_id: `${id_pre}${data.client_id}` if options.on_mc_connection :: options.on_mc_connection(chan, data) return hub => :: let direct = @{} __proto__: _direct_ p2p createDirect(dispatch, channel_id) :: if 'function' !== typeof dispatch :: throw new TypeError let [recv, channel] = hub.router.send_channel @ this.p2p || hub.p2p, dispatch return @[] recv, channel.init @ channel_id || 'direct' connectMsgPort(tgt, options={}) :: if null == options :: options = {} let [tgt_send, tgt_recv] = Array.isArray(tgt) ? tgt : [tgt, tgt] tgt_send = (tgt_send.postMessage || tgt_send.send).bind(tgt_send) let [recv, channel] = hub.router.send_channel @ this.p2p || hub.p2p pkt => @ tgt_send(pkt), true let subscribe = options.subscribe || _on_msg_evt subscribe(tgt_recv, recv) if tgt_recv.close :: channel.close = @=> @ tgt_recv.close(), true return channel.init @ options.channel_id || 'messageport' hub.direct = {__proto__: direct} function _on_msg_evt(tgt_recv, fn_recv_pkt) :: if tgt_recv.on :: tgt_recv.on @ 'message', fn_recv_pkt else :: tgt_recv.onmessage = evt => fn_recv_pkt(evt.data, evt)