Skip to content

Commit 8bf412a

Browse files
author
mattiaformenti
committed
Merge branch 'webapp_partial_results' into webapp2
2 parents d5ff3c2 + bc64347 commit 8bf412a

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Scanner Core - A Modular Framework for Probe Definition, Execution, and Result Analysis.
3+
*
4+
* Copyright 2017-2023 Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH
5+
*
6+
* Licensed under Apache License, Version 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0.txt
8+
*/
9+
package de.rub.nds.scanner.core.execution;
10+
11+
import de.rub.nds.scanner.core.probe.ScannerProbe;
12+
import de.rub.nds.scanner.core.report.ScanReport;
13+
14+
/**
15+
* Callback interface for receiving probe execution progress updates. This interface allows external
16+
* components to be notified when individual probes complete during a scan, enabling real-time
17+
* progress monitoring and streaming of partial results.
18+
*
19+
* @param <ReportT> the type of scan report
20+
* @param <StateT> the type of state object used by probes
21+
*/
22+
@FunctionalInterface
23+
public interface ProbeProgressCallback<ReportT extends ScanReport, StateT> {
24+
25+
/**
26+
* Called when a probe has completed execution and merged its results into the report.
27+
*
28+
* @param probe the probe that completed execution
29+
* @param report the scan report with the probe's results merged in
30+
* @param completedProbes the number of probes that have completed so far
31+
* @param totalProbes the total number of probes scheduled for this scan
32+
*/
33+
void onProbeCompleted(
34+
ScannerProbe<ReportT, StateT> probe,
35+
ReportT report,
36+
int completedProbes,
37+
int totalProbes);
38+
39+
/**
40+
* Creates a no-op callback that does nothing when probes complete. Useful as a default when no
41+
* progress tracking is needed.
42+
*
43+
* @param <R> the type of scan report
44+
* @param <S> the type of state object
45+
* @return a callback that performs no operations
46+
*/
47+
static <R extends ScanReport, S> ProbeProgressCallback<R, S> noOp() {
48+
return (probe, report, completedProbes, totalProbes) -> {
49+
// No operation
50+
};
51+
}
52+
}

src/main/java/de/rub/nds/scanner/core/execution/Scanner.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public abstract class Scanner<
4949
private final List<AfterProbeT> afterList;
5050
private final boolean fillProbeListsAtScanStart;
5151

52+
// Optional callback for probe progress updates
53+
private ProbeProgressCallback<ReportT, StateT> progressCallback = ProbeProgressCallback.noOp();
54+
5255
/**
5356
* Creates a new scanner instance.
5457
*
@@ -131,6 +134,18 @@ protected List<Guideline> getGuidelines() {
131134
return List.of();
132135
}
133136

137+
/**
138+
* Sets the progress callback to be invoked when probes complete during scanning. This allows
139+
* external components to receive real-time updates about scan progress and partial results.
140+
*
141+
* @param progressCallback the callback to invoke on probe completion, or null to disable
142+
* callbacks
143+
*/
144+
public void setProgressCallback(ProbeProgressCallback<ReportT, StateT> progressCallback) {
145+
this.progressCallback =
146+
progressCallback != null ? progressCallback : ProbeProgressCallback.noOp();
147+
}
148+
134149
/**
135150
* Performs the scan. It will take care of all the necessary steps to perform a scan, including
136151
* filling the probe list by calling {@link #fillProbeLists}, checking the scan prerequisites by
@@ -166,6 +181,8 @@ public ReportT scan() {
166181
scanJob,
167182
executorConfig.getParallelProbes(),
168183
"ScannerProbeExecutor " + report.getRemoteName())) {
184+
// Set the progress callback on the executor
185+
scanJobExecutor.setProgressCallback(progressCallback);
169186
ProgressSpinner.startSpinnerTask("Executing:");
170187
report.setScanStartTime(System.currentTimeMillis());
171188
scanJobExecutor.execute(report);

src/main/java/de/rub/nds/scanner/core/execution/ThreadedScanJobExecutor.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public class ThreadedScanJobExecutor<
6060
private volatile int probeCount;
6161
private final AtomicInteger finishedProbes = new AtomicInteger(0);
6262

63+
// Callback for probe progress updates (optional)
64+
private ProbeProgressCallback<ReportT, StateT> progressCallback = ProbeProgressCallback.noOp();
65+
6366
/**
6467
* Creates a new ThreadedScanJobExecutor with a custom thread pool.
6568
*
@@ -103,6 +106,18 @@ public ThreadedScanJobExecutor(
103106
this.futureResults = new LinkedList<>();
104107
}
105108

109+
/**
110+
* Sets the progress callback to be invoked when probes complete. This allows external
111+
* components to receive real-time updates about scan progress.
112+
*
113+
* @param progressCallback the callback to invoke on probe completion, or null to disable
114+
* callbacks
115+
*/
116+
public void setProgressCallback(ProbeProgressCallback<ReportT, StateT> progressCallback) {
117+
this.progressCallback =
118+
progressCallback != null ? progressCallback : ProbeProgressCallback.noOp();
119+
}
120+
106121
/**
107122
* Executes the scan job by running probes concurrently and populating the report with results.
108123
* This method manages probe dependencies and ensures probes are executed in the correct order.
@@ -146,7 +161,8 @@ private void executeProbesTillNoneCanBeExecuted(ReportT report) throws Interrupt
146161
try {
147162
probeResult = result.get();
148163
LOGGER.info(
149-
"[{}/{}] {} probe executed",
164+
"[{}] [{}/{}] {} probe executed",
165+
report.getRemoteName(),
150166
String.format("%2d", currentFinishedProbes),
151167
String.format("%2d", probeCount),
152168
probeResult.getType().getName());
@@ -157,6 +173,14 @@ private void executeProbesTillNoneCanBeExecuted(ReportT report) throws Interrupt
157173
finishedFutures.add(result);
158174
probeResult.merge(report);
159175
report.markProbeAsExecuted(probeResult);
176+
177+
// Notify progress callback
178+
try {
179+
progressCallback.onProbeCompleted(
180+
probeResult, report, currentFinishedProbes, probeCount);
181+
} catch (Exception e) {
182+
LOGGER.warn("Progress callback threw exception, continuing scan", e);
183+
}
160184
}
161185
}
162186
futureResults.removeAll(finishedFutures);

0 commit comments

Comments
 (0)