diff options
| author | 2026-04-13 17:31:55 +0200 | |
|---|---|---|
| committer | 2026-07-09 09:59:28 +0200 | |
| commit | 8b881560dd8884e8e54e1e64654f79749d9ff456 (patch) | |
| tree | faffd2348b9430bcda9591120a0aa392923e422c /src/main/java/com/it_jaros/network_scanner/Scanner.java | |
| parent | b1bdcf02479f67a65f6176ed8a87b47925903e81 (diff) | |
Renamed package from network_scanner to jscanner
Diffstat (limited to 'src/main/java/com/it_jaros/network_scanner/Scanner.java')
| -rw-r--r-- | src/main/java/com/it_jaros/network_scanner/Scanner.java | 209 |
1 files changed, 0 insertions, 209 deletions
diff --git a/src/main/java/com/it_jaros/network_scanner/Scanner.java b/src/main/java/com/it_jaros/network_scanner/Scanner.java deleted file mode 100644 index 070a164..0000000 --- a/src/main/java/com/it_jaros/network_scanner/Scanner.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.it_jaros.network_scanner; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.*; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.List; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.LockSupport; -import java.util.stream.Stream; - -public class Scanner { - - private final Counter counter = new Counter(); - private final ProgressBar progressBar = new ProgressBar(); - private final Semaphore socketLimit; - private final int timeoutInMillis; - private final long delayInNanos; - private final int maxWorkersPerHost; - private final int maxHostsLimit; - private final boolean disableHostCheck; - - public Scanner(int socketLimit, int timeoutInMillis, int delayInMillis, int maxWorkersPerHost, int maxHostsLimit, boolean disableHostCheck) { - this.timeoutInMillis = timeoutInMillis; - this.delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis)); - this.socketLimit = new Semaphore(socketLimit); - this.maxWorkersPerHost = maxWorkersPerHost; - this.maxHostsLimit = maxHostsLimit; - this.disableHostCheck = disableHostCheck; - } - - public List<ScanResult> scan(ScanOptions options) { - if (options.hostsFile() != null) { - return scanHosts(options.hostsFile(), options.ports()); - } - return scanHosts(options.hostsArgv(), options.ports()); - } - - public List<ScanResult> scanHosts(String sourceFile, String ports) { - try (BufferedReader reader = Files.newBufferedReader(Path.of(sourceFile))) { - return scanHosts(reader.lines(), ports); - } catch (FileNotFoundException | NoSuchFileException e) { - System.out.printf("Could not open file %s%n", sourceFile); - } catch (IOException e) { - System.out.printf("Error while trying to read hosts: %s -> %s %n", e.getClass().getSimpleName(), e.getMessage()); - } - - return List.of(); - } - - public List<ScanResult> scanHosts(List<String> hostsArgv, String ports) { - try (Stream<String> stream = hostsArgv.stream()){ - return scanHosts(stream, ports); - } catch (IOException e) { - System.out.printf("Error while trying to read hosts: %s -> %s %n", e.getClass().getSimpleName(), e.getMessage()); - } - - return List.of(); - } - - public List<ScanResult> scanHosts(Stream<String> hosts, String ports) throws IOException { - List<ScanResult> results = new ArrayList<>(); - progressBar.start(); - try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { - List<Future<ScanResult>> futures = new ArrayList<>(); - Semaphore maxHosts = new Semaphore(maxHostsLimit); - hosts.forEach((final String host) -> { - maxHosts.acquireUninterruptibly(); - futures.add(executor.submit(() -> { - try { - return scanHost(host, ports); - } finally { - maxHosts.release(); - } - })); - }); - - futures.forEach((Future<ScanResult> f) -> { - try { - results.add(f.get()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (ExecutionException e) { - System.out.printf("%s -> %s%n", e.getClass().getSimpleName(), e.getMessage()); - } - }); - } - - progressBar.stop(); - System.out.println("--------------------"); - System.out.println("Finished scan!"); - System.out.println("Stats:"); - System.out.println("Peak concurrent connects: " + counter.max()); - System.out.println("--------------------"); - return results; - } - - private ScanResult scanHost(String host, String ports) { - PortRange portRange = new PortRange(ports); - AtomicLong portSlotFactory = new AtomicLong(System.nanoTime()); - Semaphore maxWorkers = new Semaphore(maxWorkersPerHost); - BitSet openPorts = new BitSet(PortRange.MAX_PORT); - BitSet filteredPorts = new BitSet(PortRange.MAX_PORT); - - Progress progress = new Progress(host, portRange.getTotal(), new AtomicInteger(), new AtomicInteger(), new AtomicInteger()); - progressBar.submit(progress); - - if(!disableHostCheck && !checkHostOnline(host)) { - // Visually show that this host is basically done - progress.done().set(progress.total()); - return new ScanResult(host, openPorts, filteredPorts); - } - - try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { - List<Future<PortResult>> futures = new ArrayList<>(); - while (portRange.hasNext()) { - maxWorkers.acquireUninterruptibly(); - final int currentPort = portRange.next(); - futures.add(executor.submit(() -> { - try { - waitForSlot(portSlotFactory); - PortState state = getPortState(host, currentPort); - if (state.equals(PortState.OPEN)) { - progress.open().incrementAndGet(); - } else if (state.equals(PortState.FILTERED)) { - progress.filtered().incrementAndGet(); - } - return new PortResult(currentPort, state); - } finally { - maxWorkers.release(); - progress.done().incrementAndGet(); - } - })); - } - - List<Throwable> errors = new ArrayList<>(); - for (Future<PortResult> f : futures) { - try { - // bitset is not thread-safe, so it is set - // outside the other virtual threads that update progress - PortResult portResult = f.get(); - if (portResult.state().equals(PortState.OPEN)) { - openPorts.set(portResult.port()); - } else if (portResult.state().equals(PortState.FILTERED)) { - filteredPorts.set(portResult.port()); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (ExecutionException e) { - errors.add(e); - } - } - - if (!errors.isEmpty()) { - System.out.printf("Errors happened during scan of host %s%nErrors:%s -> %s", host, errors.size(), errors); - } - } - - return new ScanResult(host, openPorts, filteredPorts); - } - - private boolean checkHostOnline(String host) { - try { - return InetAddress.getByName(host).isReachable(timeoutInMillis); - } catch (IOException e) { - // something went wrong - } - - return false; - } - - private void waitForSlot(AtomicLong scanSlotFactory) { - if (delayInNanos > 0) { - long slot = scanSlotFactory.getAndAdd(delayInNanos); - long wait = slot - System.nanoTime(); - if (wait > 0) - LockSupport.parkNanos(wait); - } - } - - private PortState getPortState(String host, int port) { - socketLimit.acquireUninterruptibly(); - counter.inc(); - try (Socket socket = new Socket()) { - socket.connect(new InetSocketAddress(host, port), timeoutInMillis); - return PortState.OPEN; - } catch (NoRouteToHostException ignored) { - // this can be safely ignored because the port is closed if a host is unreachable - } catch (SocketTimeoutException ignored) { - return PortState.FILTERED; - } catch (ConnectException ignored) { - return PortState.CLOSED; - } catch (IOException ignored) { - // Will happen a lot when scanning for open ports, so not needed - } finally { - counter.dec(); - socketLimit.release(); - } - - return PortState.CLOSED; - } -} |
