8 function formatTime(seconds, selectCount) {
9 var days = Math.floor(seconds / (60 * 60 * 24));
10 var hours = Math.floor(seconds / (60 * 60)) % 24;
11 var minutes = Math.floor(seconds / 60) % 60;
12 var seconds = Math.floor(seconds % 60);
15 [days, _('Day'), _('Days')],
16 [hours, _('Hour'), _('Hours')],
17 [minutes, _('Minute'), _('Minutes')],
18 [seconds, _('Second'), _('Seconds')]
19 ].filter(function ([time, singular, plural]) {
23 var selectedTimes = times.slice(0, selectCount);
24 return selectedTimes.map(function ([time, singular, plural]) {
25 var unit = time > 1 ? plural : singular;
26 return '%d %s'.format(time, unit);
30 function buildSection(name, table) {
31 return E('div', { 'class': 'cbi-section' }, [
37 function buildTable(rows) {
38 return E('table', { 'class': 'table', }, rows);
41 function buildKeyValueTable(kvPairs) {
42 var rows = kvPairs.map(function (row) {
43 return E('tr', { 'class': 'tr' }, [
44 E('td', { 'class': 'td', 'width': '33%' }, E('strong', [row[0]])),
45 E('td', { 'class': 'td' }, [row[1]])
48 return buildTable(rows);
51 function collectErrorMessages(results) {
52 var errorMessages = results.reduce(function (messages, result) {
53 return messages.concat(result.errors.map(function (error) {
57 var uniqueErrorMessages = new Set(errorMessages);
59 return [...uniqueErrorMessages];
65 fs.exec_direct('/usr/sbin/swanmon', ['version'], 'json'),
66 fs.exec_direct('/usr/sbin/swanmon', ['stats'], 'json'),
67 fs.exec_direct('/usr/sbin/swanmon', ['list-sas'], 'json')
71 pollData: function (container) {
72 poll.add(L.bind(function () {
73 return this.load().then(L.bind(function (results) {
74 dom.content(container, this.renderContent(results));
79 renderContent: function (results) {
80 var node = E('div', [E('div')]);
81 var firstNode = node.firstElementChild;
83 var errorMessages = collectErrorMessages(results);
84 if (errorMessages.length > 0) {
85 var messageEls = errorMessages.map(function (message) {
86 return E('li', message);
89 firstNode.appendChild(E('h4', _('Querying strongSwan failed')));
90 firstNode.appendChild(E('ul', messageEls));
95 var [version, stats, sas] = results.map(function (r) {
99 var uptimeSeconds = (new Date() - new Date(stats.uptime.since)) / 1000;
100 var statsSection = buildSection(_('Stats'), buildKeyValueTable([
101 [_('Version'), version.version],
102 [_('Uptime'), formatTime(uptimeSeconds, 2)],
103 [_('Daemon'), version.daemon],
104 [_('Active IKE_SAs'), stats.ikesas.total],
105 [_('Half-Open IKE_SAs'), stats.ikesas['half-open']]
107 firstNode.appendChild(statsSection);
109 var tableRows = sas.map(function (conn) {
110 var name = Object.keys(conn)[0];
111 var data = conn[name];
114 Object.entries(data['child-sas']).forEach(function ([name, data]) {
115 var table = buildKeyValueTable([
116 [_('State'), data.state],
117 [_('Mode'), data.mode],
118 [_('Protocol'), data.protocol],
119 [_('Local Traffic Selectors'), data['local-ts'].join(', ')],
120 [_('Remote Traffic Selectors'), data['remote-ts'].join(', ')],
121 [_('Encryption Algorithm'), data['encr-alg']],
122 [_('Encryption Keysize'), data['encr-keysize']],
123 [_('Bytes in'), data['bytes-in']],
124 [_('Bytes out'), data['bytes-out']],
125 [_('Life Time'), formatTime(data['life-time'], 2)],
126 [_('Install Time'), formatTime(data['install-time'], 2)],
127 [_('Rekey in'), formatTime(data['rekey-time'], 2)],
128 [_('SPI in'), data['spi-in']],
129 [_('SPI out'), data['spi-out']]
131 childSas.push(E('div', { 'class': 'cbi-section' }, [
132 E('h4', { 'style': 'margin-top: 0; padding-top: 0;' }, [name]),
136 childSas.push(E('button', {
137 'class': 'btn cbi-button cbi-button-apply',
138 'click': ui.hideModal
141 return E('tr', { 'class': 'tr' }, [
142 E('td', { 'class': 'td' }, [name]),
143 E('td', { 'class': 'td' }, [data.state]),
144 E('td', { 'class': 'td' }, [data['remote-host']]),
145 E('td', { 'class': 'td' }, [data.version]),
146 E('td', { 'class': 'td' }, [formatTime(data.established, 2)]),
147 E('td', { 'class': 'td' }, [formatTime(data['reauth-time'], 2)]),
148 E('td', { 'class': 'td' }, [E('button', {
149 'class': 'btn cbi-button cbi-button-apply',
150 'click': function (ev) {
151 ui.showModal(_('CHILD_SAs'), childSas)
153 }, _('Show Details'))])
156 var connSection = buildSection(_('Security Associations (SAs)'), buildTable([
157 E('tr', { 'class': 'tr' }, [
158 E('th', { 'class': 'th' }, [_('Name')]),
159 E('th', { 'class': 'th' }, [_('State')]),
160 E('th', { 'class': 'th' }, [_('Remote')]),
161 E('th', { 'class': 'th' }, [_('IKE Version')]),
162 E('th', { 'class': 'th' }, [_('Established for')]),
163 E('th', { 'class': 'th' }, [_('Reauthentication in')]),
164 E('th', { 'class': 'th' }, [_('Details')])
168 firstNode.appendChild(connSection);
173 render: function (results) {
174 var content = E([], [
175 E('h2', [_('strongSwan Status')]),
178 var container = content.lastElementChild;
180 dom.content(container, this.renderContent(results));
181 this.pollData(container);
186 handleSaveApply: null,