Files: 82418e8c0eab5c0b94532a1f8612097db1fc1bb4 / modules / network.js
3367 bytesRaw
1 | var isVisible = require('is-visible').isVisible |
2 | var human = require('human-time') |
3 | var h = require('hyperscript') |
4 | |
5 | exports.needs = { |
6 | avatar: 'first', |
7 | sbot_gossip_peers: 'first', |
8 | sbot_gossip_connect: 'first' |
9 | } |
10 | |
11 | exports.gives = { |
12 | screen_view: true |
13 | } |
14 | |
15 | function legacyToMultiServer(addr) { |
16 | return 'net:'+addr.host + ':'+addr.port + '~shs:'+addr.key.substring(1).replace('.ed25519','') |
17 | } |
18 | |
19 | function isLocal (e) { |
20 | return ip.isPrivate(e.host) && e.type === 'local' |
21 | } |
22 | |
23 | function isLongterm (e) { |
24 | return e.ping && e.ping.rtt && e.ping.rtt.mean > 0 |
25 | } |
26 | |
27 | function isLegacy (peer) { |
28 | return /connect/.test(peer.state) || (peer.duration && peer.duration.mean) > 0 && !isLongterm(peer) |
29 | } |
30 | |
31 | function isInactive (e) { |
32 | return e.stateChange && (e.duration && e.duration.mean == 0) |
33 | } |
34 | |
35 | function isUnattempted (e) { |
36 | return !e.stateChange |
37 | } |
38 | |
39 | function getType (e) { |
40 | return ( |
41 | isLongterm(e) ? 'modern' |
42 | : isLegacy(e) ? 'legacy' |
43 | : isInactive(e) ? 'inactive' |
44 | : isUnattempted(e) ? 'unattempted' |
45 | : 'other' //should never happen |
46 | ) |
47 | } |
48 | |
49 | function origin (e) { |
50 | return e.source === 'local' ? 0 : 1 |
51 | } |
52 | |
53 | var states = { |
54 | connected: 3, |
55 | connecting: 2 |
56 | } |
57 | |
58 | var types = { |
59 | modern: 4, |
60 | legacy: 3, |
61 | inactive: 2, |
62 | unattempted: 1, |
63 | other: 0 |
64 | } |
65 | |
66 | function round(n) { |
67 | return Math.round(n*100)/100 |
68 | } |
69 | |
70 | function duration (s) { |
71 | if(!s) return s |
72 | if (Math.abs(s) > 30000) |
73 | return round(s/60000)+'m' |
74 | else if (Math.abs(s) > 500) |
75 | return round(s/1000)+'s' |
76 | else |
77 | return round(s)+'ms' |
78 | } |
79 | |
80 | exports.create = function (api) { |
81 | |
82 | return { |
83 | screen_view: function (path) { |
84 | |
85 | if(path !== 'Network') return |
86 | |
87 | var ol = h('div.network') |
88 | |
89 | ;(function poll () { |
90 | |
91 | if(!isVisible(ol)) |
92 | return setTimeout(poll, 1000) |
93 | |
94 | api.sbot_gossip_peers(function (err, list) { |
95 | ol.innerHTML = '' |
96 | list.sort(function (a, b) { |
97 | return ( |
98 | (states[b.state] || 0) - (states[a.state] || 0) |
99 | || origin(b) - origin(a) |
100 | || types[getType(b)] - types[getType(a)] |
101 | || b.stateChange - a.stateChange |
102 | ) |
103 | }).forEach(function (peer) { |
104 | ol.appendChild(h('div.message', |
105 | api.avatar(peer.key, 'thumbnail'), |
106 | h('div', |
107 | peer.state || 'not connected', |
108 | ' ', |
109 | getType(peer), |
110 | ' ', |
111 | (peer.ping && peer.ping.rtt) ? duration(peer.ping.rtt.mean) : '', |
112 | ' ', |
113 | (peer.ping && peer.ping.skew) ? duration(peer.ping.skew.mean) : '', |
114 | h('label', |
115 | {title: new Date(peer.stateChange).toString()}, |
116 | peer.stateChange && ('(' + human(new Date(peer.stateChange))) + ')') |
117 | ), |
118 | 'source:'+peer.source, |
119 | h('pre', legacyToMultiServer(peer)), |
120 | h('button', 'connect', {onclick: function () { |
121 | api.sbot_gossip_connect(peer, function (err) { |
122 | if(err) console.error(err) |
123 | else console.log('connected to', peer) |
124 | }) |
125 | }}) |
126 | ) |
127 | ) |
128 | }) |
129 | setTimeout(poll, 1000) |
130 | }) |
131 | })() |
132 | return h('div.column.scroller', h('div.column.scroll-y', h('div.column.scroller__wrapper', ol))) |
133 | } |
134 | } |
135 | } |
136 | |
137 | |
138 |
Built with git-ssb-web