wavehunter: add QMDL storage

Instead of reading/writing to a single QMDL file, we now can manage
a directory of several files, and have the ability to start/stop writing
to them on the fly.

This commit also adds graceful exiting to the server, so we can perform
cleanup steps when the server's exiting.
This commit is contained in:
Will Greenberg
2024-01-10 15:47:52 -08:00
parent 3d869971d9
commit 7b972ef5e4
14 changed files with 742 additions and 126 deletions

View File

@@ -1,24 +1,90 @@
async function populateDivs() {
const systemStats = await getSystemStats();
const diagStats = await getDiagStats();
const systemStatsDiv = document.getElementById('system-stats');
const diagStatsDiv = document.getElementById('diag-stats');
systemStatsDiv.innerHTML = JSON.stringify(systemStats, null, 2);
diagStatsDiv.innerHTML = JSON.stringify(diagStats, null, 2);
const qmdlManifest = await getQmdlManifest();
updateQmdlManifestTable(qmdlManifest);
}
function updateQmdlManifestTable(manifest) {
const table = document.getElementById('qmdl-manifest-table');
const numRows = table.rows.length;
for (let i=1; i<numRows; i++) {
table.deleteRow(1);
}
if (manifest.current_entry) {
const row = createEntryRow(manifest.current_entry);
row.classList.add('current');
table.appendChild(row)
}
for (let entry of manifest.entries) {
table.appendChild(createEntryRow(entry));
}
}
function createEntryRow(entry) {
const row = document.createElement('tr');
const name = document.createElement('th');
name.scope = 'row';
name.innerText = entry.name;
row.appendChild(name);
for (const key of ['start_time', 'end_time', 'size_bytes']) {
const td = document.createElement('td');
td.innerText = entry[key];
row.appendChild(td);
}
const pcap_td = document.createElement('td');
const pcap_link = document.createElement('a');
pcap_link.href = `/api/pcap/${entry.name}`;
pcap_link.innerText = 'pcap';
pcap_td.appendChild(pcap_link);
row.appendChild(pcap_td);
const qmdl_td = document.createElement('td');
const qmdl_link = document.createElement('a');
qmdl_link.href = `/api/qmdl/${entry.name}`;
qmdl_link.innerText = 'qmdl';
qmdl_td.appendChild(qmdl_link);
row.appendChild(qmdl_td);
return row;
}
async function getSystemStats() {
return await getJson('/api/system-stats');
return JSON.parse(await req('GET', '/api/system-stats'));
}
async function getDiagStats() {
return await getJson('/api/diag-stats');
async function getQmdlManifest() {
const manifest = JSON.parse(await req('GET', '/api/qmdl-manifest'));
if (manifest.current_entry) {
manifest.current_entry.start_time = new Date(manifest.current_entry.start_time);
}
for (entry of manifest.entries) {
entry.start_time = new Date(entry.start_time);
entry.end_time = new Date(entry.end_time);
}
// sort them in reverse chronological order
manifest.entries.reverse();
return manifest;
}
async function getJson(url) {
const response = await fetch(url);
const data = await response.json();
return data;
async function startRecording() {
await req('POST', '/api/start-recording');
populateDivs();
}
async function stopRecording() {
await req('POST', '/api/stop-recording');
populateDivs();
}
async function req(method, url) {
const response = await fetch(url, {
method: method,
});
const body = await response.text();
if (response.status >= 200 && response.status < 300) {
return body;
} else {
throw new Error(body);
}
}