export function p2p_plugin() :: return hub => :: hub._root_.p2p = bind_basic_p2p(hub) export function bind_basic_p2p(hub) :: const ts_2020 = 1577836800000 return @{} initForChannel(channel) :: return Object.create @ this, @{} channel: @{} value: channel router: @{} value: channel.router ms_timeout: 5000 async hello(ms_timeout=this.ms_timeout) :: let { channel, router } = this let xt = router.timeouts let id_reply = hub.randId(6) let dp = router.timeouts.ao_defer_v() this[ '_m$_' + id_reply ] = dp[1] if ms_timeout :: xt.add @ ms_timeout, () => dp[1](null) let ival_cancel = xt.interval @ {ms: 250, initial: true}, () => channel.send @ '', 'hello', @{} version: this.version, id_reply, ts: +new Date() let ans try :: ans = await dp[0] finally :: ival_cancel() delete this[ '_m$_' + id_reply ] let { public_routes } = router for let id_route of Object(ans).routes || [] :: // Keep local public routes local if ! public_routes.get(id_route) :: channel.addRoute @ id_route, false for let fn of this._q :: dp[0].then(fn) return ans peerRoute(pkt) :: let {1: id_target, body} = pkt let fn = this[ '_m$_' + id_target ] return fn ? fn.call(this, body) : null _m$_hello(body) :: let {version, id_reply} = Object(body) if this.version !== version :: return if ! id_reply :: return return this.channel.send @ '', id_reply, @{} ... this.info, version, ts: Date.now() - ts_2020, routes: Array.from @ this.router.public_routes.keys() version: 'basic' info: {} with_info(info) :: this.info = {... this.info, ...info} return this _q: [] on(...fn_args) :: this._q = this._q.concat(fn_args) return this