mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-23 16:26:16 -04:00
146 lines
4.9 KiB
JavaScript
146 lines
4.9 KiB
JavaScript
![]() |
/**
|
||
|
* @author n1474335 [n1474335@gmail.com]
|
||
|
* @copyright Crown Copyright 2023
|
||
|
* @license Apache-2.0
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Waiter to handle timing of the baking process.
|
||
|
*/
|
||
|
class TimingWaiter {
|
||
|
|
||
|
/**
|
||
|
* TimingWaiter constructor.
|
||
|
*
|
||
|
* @param {App} app - The main view object for CyberChef.
|
||
|
* @param {Manager} manager - The CyberChef event manager.
|
||
|
*/
|
||
|
constructor(app, manager) {
|
||
|
this.app = app;
|
||
|
this.manager = manager;
|
||
|
|
||
|
this.inputs = {};
|
||
|
/*
|
||
|
Inputs example:
|
||
|
"1": {
|
||
|
"inputEncodingStart": 0,
|
||
|
"inputEncodingEnd": 0,
|
||
|
"trigger": 0
|
||
|
"chefWorkerTasked": 0,
|
||
|
"bakeComplete": 0,
|
||
|
"bakeDuration": 0,
|
||
|
"settingOutput": 0,
|
||
|
"outputDecodingStart": 0,
|
||
|
"outputDecodingEnd": 0,
|
||
|
"complete": 0
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Record the time for an input
|
||
|
*
|
||
|
* @param {string} event
|
||
|
* @param {number} inputNum
|
||
|
* @param {number} value
|
||
|
*/
|
||
|
recordTime(event, inputNum, value=Date.now()) {
|
||
|
inputNum = inputNum.toString();
|
||
|
if (!Object.keys(this.inputs).includes(inputNum)) {
|
||
|
this.inputs[inputNum] = {};
|
||
|
}
|
||
|
log.debug(`Recording ${event} for input ${inputNum}`);
|
||
|
this.inputs[inputNum][event] = value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The total time for a completed bake
|
||
|
*
|
||
|
* @param {number} inputNum
|
||
|
* @returns {number}
|
||
|
*/
|
||
|
overallDuration(inputNum) {
|
||
|
const input = this.inputs[inputNum.toString()];
|
||
|
|
||
|
// If this input has not been encoded yet, we cannot calculate a time
|
||
|
if (!input ||
|
||
|
!input.trigger ||
|
||
|
!input.inputEncodingEnd ||
|
||
|
!input.inputEncodingStart)
|
||
|
return 0;
|
||
|
|
||
|
// input encoding can happen before a bake is triggered, so it is calculated separately
|
||
|
const inputEncodingTotal = input.inputEncodingEnd - input.inputEncodingStart;
|
||
|
|
||
|
let total = 0;
|
||
|
if (input.bakeComplete && input.bakeComplete > input.trigger)
|
||
|
total = input.bakeComplete - input.trigger;
|
||
|
|
||
|
if (input.settingOutput && input.settingOutput > input.trigger)
|
||
|
total = input.settingOutput - input.trigger;
|
||
|
|
||
|
if (input.outputDecodingStart && input.outputDecodingStart > input.trigger)
|
||
|
total = input.outputDecodingStart - input.trigger;
|
||
|
|
||
|
if (input.outputDecodingEnd && input.outputDecodingEnd > input.trigger)
|
||
|
total = input.outputDecodingEnd - input.trigger;
|
||
|
|
||
|
if (input.complete && input.complete > input.trigger)
|
||
|
total = input.complete - input.trigger;
|
||
|
|
||
|
return total + inputEncodingTotal;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Prints out the time between stages
|
||
|
*
|
||
|
* @param {number} inputNum
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
printStages(inputNum) {
|
||
|
const input = this.inputs[inputNum.toString()];
|
||
|
if (!input || !input.trigger) return "";
|
||
|
this.logAllTimes(inputNum);
|
||
|
|
||
|
const total = this.overallDuration(inputNum),
|
||
|
inputEncoding = input.inputEncodingEnd - input.inputEncodingStart,
|
||
|
outputDecoding = input.outputDecodingEnd - input.outputDecodingStart,
|
||
|
overhead = total - inputEncoding - outputDecoding - input.bakeDuration;
|
||
|
|
||
|
return `Input encoding: ${inputEncoding}ms
|
||
|
Recipe duration: ${input.bakeDuration}ms
|
||
|
Output decoding: ${outputDecoding}ms
|
||
|
Threading overhead: ${overhead}ms
|
||
|
Total: ${total}ms`;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Logs every interval
|
||
|
*
|
||
|
* @param {number} inputNum
|
||
|
*/
|
||
|
logAllTimes(inputNum) {
|
||
|
const input = this.inputs[inputNum.toString()];
|
||
|
if (!input || !input.trigger) return;
|
||
|
|
||
|
try {
|
||
|
log.debug(`Trigger: ${input.trigger}
|
||
|
inputEncodingStart: ${input.inputEncodingStart} | ${input.inputEncodingStart - input.trigger}ms since trigger
|
||
|
inputEncodingEnd: ${input.inputEncodingEnd} | ${input.inputEncodingEnd - input.inputEncodingStart}ms input encoding time
|
||
|
chefWorkerTasked: ${input.chefWorkerTasked} | ${input.chefWorkerTasked - input.trigger}ms since trigger
|
||
|
bakeDuration: | ${input.bakeDuration}ms duration in worker
|
||
|
bakeComplete: ${input.bakeComplete} | ${input.bakeComplete - input.chefWorkerTasked}ms since worker tasked
|
||
|
settingOutput: ${input.settingOutput} | ${input.settingOutput - input.bakeComplete}ms since worker finished
|
||
|
outputDecodingStart: ${input.outputDecodingStart} | ${input.outputDecodingStart - input.settingOutput}ms since output set
|
||
|
outputDecodingEnd: ${input.outputDecodingEnd} | ${input.outputDecodingEnd - input.outputDecodingStart}ms output encoding time
|
||
|
complete: ${input.complete} | ${input.complete - input.outputDecodingEnd}ms since output decoded
|
||
|
Total: | ${input.complete - input.trigger}ms since trigger`);
|
||
|
} catch (err) {}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
export default TimingWaiter;
|