mirror of
https://github.com/angryip/ipscan.git
synced 2025-10-26 11:18:17 +00:00
make it possible to terminate socket operations in progress (this is possible by calling socket.close() from another thread)
This commit is contained in:
parent
74710d8d77
commit
21a202062b
@ -10,6 +10,9 @@ import net.azib.ipscan.core.values.NotScanned;
|
||||
import net.azib.ipscan.fetchers.Fetcher;
|
||||
import net.azib.ipscan.fetchers.FetcherRegistry;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Scanner functionality is encapsulated in this class.
|
||||
* It uses a list of fetchers to perform the actual scanning.
|
||||
@ -17,8 +20,8 @@ import net.azib.ipscan.fetchers.FetcherRegistry;
|
||||
* @author Anton Keks
|
||||
*/
|
||||
public class Scanner {
|
||||
|
||||
private FetcherRegistry fetcherRegistry;
|
||||
private Map<Long, Fetcher> currentFetchers = new ConcurrentHashMap<Long, Fetcher>();
|
||||
|
||||
public Scanner(FetcherRegistry fetcherRegistry) {
|
||||
this.fetcherRegistry = fetcherRegistry;
|
||||
@ -34,6 +37,7 @@ public class Scanner {
|
||||
int fetcherIndex = 0;
|
||||
boolean isScanningInterrupted = false;
|
||||
for (Fetcher fetcher : fetcherRegistry.getSelectedFetchers()) {
|
||||
currentFetchers.put(Thread.currentThread().getId(), fetcher);
|
||||
Object value = NotScanned.VALUE;
|
||||
if (!subject.isAddressAborted() && !isScanningInterrupted) {
|
||||
// run the fetcher
|
||||
@ -50,6 +54,11 @@ public class Scanner {
|
||||
|
||||
result.setType(subject.getResultType());
|
||||
}
|
||||
|
||||
public void interrupt(Thread thread) {
|
||||
Fetcher fetcher = currentFetchers.get(thread.getId());
|
||||
if (fetcher != null) fetcher.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init everything needed for scanning, including Fetchers
|
||||
@ -64,9 +73,9 @@ public class Scanner {
|
||||
* Cleanup after a scan
|
||||
*/
|
||||
public void cleanup() {
|
||||
currentFetchers.clear();
|
||||
for (Fetcher fetcher : fetcherRegistry.getSelectedFetchers()) {
|
||||
fetcher.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -158,11 +158,15 @@ public class ScannerDispatcherThread extends Thread implements ThreadFactory, St
|
||||
*/
|
||||
public Thread newThread(Runnable r) {
|
||||
// create IP threads in the specified group
|
||||
Thread thread = new Thread(threadGroup, r);
|
||||
// IP threads must be daemons, not preventing the JVM to terminate
|
||||
thread.setDaemon(true);
|
||||
|
||||
return thread;
|
||||
return new Thread(threadGroup, r) {
|
||||
// IP threads must be daemons, not preventing the JVM to terminate
|
||||
{ setDaemon(true); }
|
||||
@Override
|
||||
public void interrupt() {
|
||||
scanner.interrupt(this);
|
||||
super.interrupt();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,16 +6,18 @@
|
||||
|
||||
package net.azib.ipscan.fetchers;
|
||||
|
||||
import net.azib.ipscan.config.LoggerFactory;
|
||||
import net.azib.ipscan.config.ScannerConfig;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.azib.ipscan.config.ScannerConfig;
|
||||
import net.azib.ipscan.config.LoggerFactory;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
import static java.util.logging.Level.*;
|
||||
import static net.azib.ipscan.util.IOUtils.*;
|
||||
|
||||
/**
|
||||
* NetBIOSInfoFetcher - gathers NetBIOS info about Windows machines.
|
||||
@ -84,13 +86,11 @@ public class NetBIOSInfoFetcher extends AbstractFetcher {
|
||||
}
|
||||
catch (Exception e) {
|
||||
// bugs?
|
||||
LOG.log(Level.WARNING, null, e);
|
||||
LOG.log(WARNING, null, e);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
closeQuietly(socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static net.azib.ipscan.core.ScanningSubject.*;
|
||||
|
||||
/**
|
||||
* PingFetcher is able to ping IP addresses.
|
||||
* It returns the average round trip time of all pings sent.
|
||||
@ -53,25 +55,21 @@ public class PingFetcher extends AbstractFetcher {
|
||||
}
|
||||
|
||||
protected PingResult executePing(ScanningSubject subject) {
|
||||
|
||||
PingResult result = null;
|
||||
|
||||
if (subject.hasParameter(ScanningSubject.PARAMETER_PING_RESULT)) {
|
||||
result = (PingResult) subject.getParameter(ScanningSubject.PARAMETER_PING_RESULT);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
result = pinger.ping(subject, config.pingCount);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// if this is not a timeout
|
||||
LOG.log(Level.WARNING, "Pinging failed", e);
|
||||
// return an empty ping result
|
||||
result = new PingResult(subject.getAddress());
|
||||
}
|
||||
// remember the result for other fetchers to use
|
||||
subject.setParameter(ScanningSubject.PARAMETER_PING_RESULT, result);
|
||||
}
|
||||
if (subject.hasParameter(PARAMETER_PING_RESULT))
|
||||
return (PingResult) subject.getParameter(PARAMETER_PING_RESULT);
|
||||
|
||||
PingResult result;
|
||||
try {
|
||||
result = pinger.ping(subject, config.pingCount);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// if this is not a timeout
|
||||
LOG.log(Level.WARNING, "Pinging failed", e);
|
||||
// return an empty ping result
|
||||
result = new PingResult(subject.getAddress());
|
||||
}
|
||||
// remember the result for other fetchers to use
|
||||
subject.setParameter(PARAMETER_PING_RESULT, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
package net.azib.ipscan.fetchers;
|
||||
|
||||
import net.azib.ipscan.config.ScannerConfig;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
import net.azib.ipscan.core.ScanningResult.ResultType;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
import net.azib.ipscan.core.net.PingResult;
|
||||
import net.azib.ipscan.core.net.PingerRegistry;
|
||||
|
||||
@ -29,6 +29,6 @@ public class PingTTLFetcher extends PingFetcher {
|
||||
public Object scan(ScanningSubject subject) {
|
||||
PingResult result = executePing(subject);
|
||||
subject.setResultType(result.isAlive() ? ResultType.ALIVE : ResultType.DEAD);
|
||||
return result.isAlive() && result.getTTL() > 0 ? new Integer(result.getTTL()) : null;
|
||||
return result.isAlive() && result.getTTL() > 0 ? result.getTTL() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,16 @@
|
||||
*/
|
||||
package net.azib.ipscan.fetchers;
|
||||
|
||||
import net.azib.ipscan.config.ScannerConfig;
|
||||
import net.azib.ipscan.core.PortIterator;
|
||||
import net.azib.ipscan.core.ScanningResult.ResultType;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
import net.azib.ipscan.core.values.NotScanned;
|
||||
import net.azib.ipscan.core.values.NumericRangeList;
|
||||
import net.azib.ipscan.gui.fetchers.PortsFetcherPrefs;
|
||||
import net.azib.ipscan.util.SequenceIterator;
|
||||
import net.azib.ipscan.util.ThreadResourceBinder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -14,15 +24,6 @@ import java.util.Iterator;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.azib.ipscan.config.ScannerConfig;
|
||||
import net.azib.ipscan.core.PortIterator;
|
||||
import net.azib.ipscan.core.ScanningSubject;
|
||||
import net.azib.ipscan.core.ScanningResult.ResultType;
|
||||
import net.azib.ipscan.core.values.NotScanned;
|
||||
import net.azib.ipscan.core.values.NumericRangeList;
|
||||
import net.azib.ipscan.gui.fetchers.PortsFetcherPrefs;
|
||||
import net.azib.ipscan.util.SequenceIterator;
|
||||
|
||||
/**
|
||||
* PortsFetcher scans TCP ports.
|
||||
* Port list is obtained using the {@link net.azib.ipscan.core.PortIterator}.
|
||||
@ -37,6 +38,7 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
private static final String PARAMETER_FILTERED_PORTS = "filteredPorts";
|
||||
|
||||
private ScannerConfig config;
|
||||
private ThreadResourceBinder<Socket> sockets = new ThreadResourceBinder<Socket>();
|
||||
|
||||
// initialize preferences for this scan
|
||||
private PortIterator portIteratorPrototype;
|
||||
@ -80,7 +82,6 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
|
||||
int portTimeout = subject.getAdaptedPortTimeout();
|
||||
|
||||
Socket socket = null;
|
||||
// clone port iterator for performance instead of creating for every thread
|
||||
Iterator<Integer> portsIterator = portIteratorPrototype.copy();
|
||||
if (config.useRequestedPorts && subject.isAnyPortRequested()) {
|
||||
@ -91,11 +92,10 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
// no ports are configured for scanning
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
while (portsIterator.hasNext() && !Thread.currentThread().isInterrupted()) {
|
||||
// TODO: UDP ports?
|
||||
// TODO: reuse sockets?
|
||||
socket = new Socket();
|
||||
Socket socket = sockets.bind(new Socket());
|
||||
int port = portsIterator.next();
|
||||
try {
|
||||
// set some optimization options
|
||||
@ -108,9 +108,7 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
socket.setSendBufferSize(16);
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
if (socket.isConnected()) {
|
||||
openPorts.add(port);
|
||||
}
|
||||
if (socket.isConnected()) openPorts.add(port);
|
||||
}
|
||||
catch (SocketTimeoutException e) {
|
||||
filteredPorts.add(port);
|
||||
@ -120,29 +118,18 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
assert e instanceof ConnectException : e;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException e) {}
|
||||
sockets.closeAndUnbind(socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subject
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected SortedSet<Integer> getFilteredPorts(ScanningSubject subject) {
|
||||
return (SortedSet<Integer>) subject.getParameter(PARAMETER_FILTERED_PORTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subject
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected SortedSet<Integer> getOpenPorts(ScanningSubject subject) {
|
||||
return (SortedSet<Integer>) subject.getParameter(PARAMETER_OPEN_PORTS);
|
||||
@ -169,4 +156,8 @@ public class PortsFetcher extends AbstractFetcher {
|
||||
this.portIteratorPrototype = new PortIterator(config.portString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
sockets.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
package net.azib.ipscan.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
public class IOUtils {
|
||||
public static void closeQuietly(Socket socket) {
|
||||
try {
|
||||
if (socket != null) socket.close();
|
||||
if (socket != null) try {
|
||||
socket.close();
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
@ -16,4 +17,12 @@ public class IOUtils {
|
||||
public static void closeQuietly(DatagramSocket socket) {
|
||||
if (socket != null) socket.close();
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable closeable) {
|
||||
if (closeable != null) try {
|
||||
closeable.close();
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user