* ConfigDetector introduced to help users check their machine suitability for scanning (especially Windows users)

* ConfigDetectorDialog and GettingStartedDialog are now shown on first run
* OptionsDialog now offers the Check button for running the ConfigDetector
* TODO updated

git-svn-id: https://ipscan.svn.sourceforge.net/svnroot/ipscan/trunk@194 375186e5-ef17-0410-b0b6-91563547dcda
This commit is contained in:
angryziber 2007-08-20 21:59:08 +00:00
parent 1cf8a8abad
commit bfde324f8c
10 changed files with 385 additions and 13 deletions

4
TODO
View File

@ -1,15 +1,13 @@
Before 3.0 beta:
* sorting by columns
* check all exporters
* tooltips
* export/import of settings
* disabling of buttons/menus during scanning
* tools->delete menus
* Mac build
Before 3.0:
* getting started message
* fetcher-specific options
* multiple port support web-detect
* add new fetchers by configuration of PortTextFetcher

View File

@ -113,9 +113,9 @@ text.fetchers.info.notAvailable=Unfortunately, no additional information about t
text.about=%NAME\n\nVersion: %VERSION\nBuild: %BUILD\n\n%COPYLEFT\nVisit <a>%WEBSITE</a>\n\nJRE: %JAVA
button.OK=OK
button.cancel=Cancel
button.close=Close
button.next=Next ->
button.start=Start
button.close=&Close
button.next=&Next ->
button.start=&Start
button.start.img=images/buttons/start.png
button.stop=Stop
button.stop.img=images/buttons/stop.png
@ -131,6 +131,7 @@ button.insert=&Insert
button.add=&Add
button.left=<<
button.right=>>
button.check=Chec&k...
combobox.feeder.tooltip=IP Feeder selection. Change this if you need another source for IP addresses to scan
list.unknown.img=images/list/unknown.png
list.dead.img=images/list/dead.png

View File

@ -25,6 +25,7 @@ import net.azib.ipscan.fetchers.PingFetcher;
import net.azib.ipscan.fetchers.PingTTLFetcher;
import net.azib.ipscan.fetchers.PortsFetcher;
import net.azib.ipscan.fetchers.WebDetectFetcher;
import net.azib.ipscan.gui.ConfigDetectorDialog;
import net.azib.ipscan.gui.MainMenu;
import net.azib.ipscan.gui.MainWindow;
import net.azib.ipscan.gui.OptionsDialog;
@ -77,6 +78,7 @@ public class ComponentRegistry {
container.registerComponentInstance(Config.getOpenersConfig());
container.registerComponentInstance(Config.getFavoritesConfig());
container.registerComponentInstance(Labels.getInstance());
container.registerComponentImplementation(ConfigDetector.class);
container.registerComponentImplementation(ExporterRegistry.class);
container.registerComponentImplementation(TXTExporter.class);
@ -131,6 +133,7 @@ public class ComponentRegistry {
container.registerComponentImplementation(OpenerLauncher.class);
container.registerComponentImplementation(MainWindow.class, MainWindow.class, new Parameter[] {
new ComponentParameter("mainShell"),
anyComponentParameter,
new ComponentParameter("feederArea"),
new ComponentParameter("controlsArea"),
new ComponentParameter("feederSelectionCombo"),
@ -139,6 +142,7 @@ public class ComponentRegistry {
anyComponentParameter,
anyComponentParameter,
anyComponentParameter,
anyComponentParameter,
anyComponentParameter});
container.registerComponentImplementation(ResultTable.class, ResultTable.class, new Parameter[] {
new ComponentParameter("mainShell"),
@ -162,6 +166,7 @@ public class ComponentRegistry {
anyComponentParameter});
container.registerComponentImplementation(OptionsDialog.class);
container.registerComponentImplementation(ConfigDetectorDialog.class);
container.registerComponentImplementation(SelectFetchersDialog.class);
container.registerComponentImplementation(StatisticsDialog.class);

View File

@ -0,0 +1,166 @@
/**
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*/
package net.azib.ipscan.config;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class detects some important config parameter values
* that work reliably on the given machine, like maximum number of threads.
*
* @author Anton Keks
*/
public class ConfigDetector {
private static Logger logger;
private GlobalConfig config;
private DetectorCallback callback;
private int numConnects;
private int numCorrectReads;
public ConfigDetector(GlobalConfig config) {
this.config = config;
}
public void setCallback(DetectorCallback callback) {
this.callback = callback;
}
public void detectMaxThreads() {
// init it here to reduce stuff needed to do in constructor
logger = LoggerFactory.getLogger();
numConnects = 0;
numCorrectReads = 0;
final DetectionServerThread serverThread = new DetectionServerThread();
serverThread.setDaemon(true);
serverThread.start();
synchronized (serverThread) {
try {
// wait for port value to become available
serverThread.wait(10000);
}
catch (InterruptedException e) {
}
}
List<Thread> threads = new LinkedList<Thread>();
try {
final InetSocketAddress socketAddress = new InetSocketAddress(InetAddress.getLocalHost(), serverThread.port);
for (int i = 0; i < config.maxThreads; i++) {
if (callback != null)
callback.onDetectorTry();
Thread t = new Thread() {
public void run() {
Socket s = new Socket();
try {
s.setSoTimeout(config.portTimeout);
s.setTcpNoDelay(true);
s.setSoLinger(true, 0);
s.connect(socketAddress, config.portTimeout);
numConnects++;
byte[] buf = new byte[64];
s.getInputStream().read(buf);
if (buf[0] == 'H') {
numCorrectReads++;
if (callback != null)
callback.onDetectorSuccess();
}
s.close();
}
catch (Exception e) {
logger.log(Level.FINE, "Failure on local port " + s.getLocalPort());
}
}
};
threads.add(t);
t.start();
}
}
catch (UnknownHostException e1) {
// getLocalHost should not fail
LoggerFactory.getLogger().log(Level.WARNING, "", e1);
}
// by this time, all the thread must be finished
try {
for (Thread t : threads) {
t.join();
}
}
catch (InterruptedException e) {
}
serverThread.interrupt();
}
public int getSuccessfulConnectCount() {
return numConnects;
}
public int getSuccessfulDataReadCount() {
return numCorrectReads;
}
static class DetectionServerThread extends Thread {
int port;
public void run() {
try {
ServerSocket server = new ServerSocket(0);
//server.setSoTimeout();
port = server.getLocalPort();
synchronized (this) {
// tell the other thread that port value is now available
this.notify();
}
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Started fake server on port " + port);
}
while (!interrupted()) {
final Socket s = server.accept();
new Thread() {
public void run() {
try {
s.setTcpNoDelay(true);
s.setSoLinger(true, 0);
OutputStream stream = s.getOutputStream();
stream.write(("Hello " + s.getPort()).getBytes());
stream.flush();
sleep(10000);
s.close();
}
catch (Exception e) {
logger.log(Level.FINER, "On port " + s.getPort(), e);
}
}
}.start();
}
logger.log(Level.FINE, "Stopped fake server");
}
catch (IOException e) {
logger.log(Level.FINE, null, e);
}
}
}
public interface DetectorCallback {
void onDetectorTry();
void onDetectorSuccess();
}
}

View File

@ -16,6 +16,7 @@ public final class GlobalConfig {
private Preferences preferences;
public boolean isFirstRun;
public int maxThreads;
public int threadDelay;
public int activeFeeder;
@ -43,6 +44,7 @@ public final class GlobalConfig {
GlobalConfig(Preferences preferences) {
this.preferences = preferences;
isFirstRun = preferences.getBoolean("firstRun", true);
maxThreads = preferences.getInt("maxThreads", 100);
threadDelay = preferences.getInt("threadDelay", 20);
activeFeeder = preferences.getInt("activeFeeder", 0);
@ -65,6 +67,7 @@ public final class GlobalConfig {
* Stores all the internal properties to the storage media
*/
public void store() {
preferences.putBoolean("firstRun", isFirstRun);
preferences.putInt("maxThreads", maxThreads);
preferences.putInt("threadDelay", threadDelay);
preferences.putInt("activeFeeder", activeFeeder);

View File

@ -0,0 +1,169 @@
/**
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*/
package net.azib.ipscan.gui;
import net.azib.ipscan.config.ConfigDetector;
import net.azib.ipscan.config.GlobalConfig;
import net.azib.ipscan.config.Labels;
import net.azib.ipscan.gui.util.LayoutHelper;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
/**
* ConfigDetectorDialog - a GUI for {@link ConfigDetector}
*
* @author Anton Keks
*/
public class ConfigDetectorDialog extends AbstractModalDialog implements ConfigDetector.DetectorCallback {
private GlobalConfig config;
private ConfigDetector configDetector;
private ProgressBar tryProgressBar;
private int tryCount;
private ProgressBar successProgressBar;
private int successCount;
private Button startButton;
private Button closeButton;
private Label tryCountLabel;
private Label successCountLabel;
public ConfigDetectorDialog(GlobalConfig config, ConfigDetector configDetector) {
this.config = config;
this.configDetector = configDetector;
this.configDetector.setCallback(this);
}
@Override
public void open() {
createShell();
super.open();
}
/**
* This method initializes shell
*/
private void createShell() {
Display currentDisplay = Display.getCurrent();
Shell parent = currentDisplay != null ? currentDisplay.getActiveShell() : null;
shell = new Shell(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
shell.setLayout(LayoutHelper.formLayout(10, 10, 10));
shell.setText(Labels.getLabel("title.configDetect"));
Label infoLabel = new Label(shell, SWT.WRAP);
infoLabel.setText((config.isFirstRun ? Labels.getLabel("text.configDetect.firstRun") : "") + Labels.getLabel("text.configDetect"));
infoLabel.setLayoutData(LayoutHelper.formData(340, SWT.DEFAULT, new FormAttachment(0), new FormAttachment(100), new FormAttachment(0), null));
Label tryLabel = new Label(shell, SWT.NONE);
tryLabel.setText(Labels.getLabel("text.configDetect.tries"));
tryLabel.setLayoutData(LayoutHelper.formData(new FormAttachment(0), null, new FormAttachment(infoLabel, 10), null));
tryCountLabel = new Label(shell, SWT.NONE);
tryCountLabel.setLayoutData(LayoutHelper.formData(new FormAttachment(tryLabel, -5), new FormAttachment(100), new FormAttachment(infoLabel, 10), null));
tryProgressBar = new ProgressBar(shell, SWT.NONE);
tryProgressBar.setLayoutData(LayoutHelper.formData(new FormAttachment(0), new FormAttachment(100), new FormAttachment(tryLabel), null));
Label successLabel = new Label(shell, SWT.NONE);
successLabel.setText(Labels.getLabel("text.configDetect.successes"));
successLabel.setLayoutData(LayoutHelper.formData(new FormAttachment(0), null, new FormAttachment(tryProgressBar, 10), null));
successCountLabel = new Label(shell, SWT.NONE);
successCountLabel.setLayoutData(LayoutHelper.formData(new FormAttachment(successLabel, -5), new FormAttachment(100), new FormAttachment(tryProgressBar, 10), null));
successProgressBar = new ProgressBar(shell, SWT.NONE);
successProgressBar.setLayoutData(LayoutHelper.formData(new FormAttachment(0), new FormAttachment(100), new FormAttachment(successLabel), null));
startButton = new Button(shell, SWT.NONE);
startButton.setText(Labels.getLabel("button.start"));
startButton.addListener(SWT.Selection, new StartButtonListener());
closeButton = new Button(shell, SWT.NONE);
closeButton.setText(Labels.getLabel("button.close"));
closeButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
shell.close();
}
});
positionButtonsInFormLayout(startButton, closeButton, successProgressBar);
shell.pack();
}
public void onDetectorTry() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
tryCount++;
tryCountLabel.setText(Integer.toString(tryCount));
tryProgressBar.setSelection(tryCount);
}
});
}
public void onDetectorSuccess() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
successCount++;
successCountLabel.setText(Integer.toString(successCount));
successProgressBar.setSelection(successCount);
}
});
}
private void onStart() {
startButton.setEnabled(false);
closeButton.setEnabled(false);
tryCount = 0;
tryCountLabel.setText("0");
tryProgressBar.setMaximum(config.maxThreads);
tryProgressBar.setSelection(0);
successCount = 0;
successCountLabel.setText("0");
successProgressBar.setMaximum(config.maxThreads);
successProgressBar.setSelection(0);
}
private void onFinish() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
startButton.setEnabled(true);
closeButton.setEnabled(true);
// ask the user if they want to use the detected value
if (config.isFirstRun || config.maxThreads != successCount) {
MessageBox box = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_QUESTION);
box.setText(Labels.getLabel("title.configDetect"));
box.setMessage(String.format(Labels.getLabel("text.configDetect.setMaxThreads"), successCount) +
(config.isFirstRun ? Labels.getLabel("text.configDetect.setMaxThreads.firstRun") : ""));
if (box.open() == SWT.YES) {
config.maxThreads = successCount;
shell.close();
}
}
}
});
}
private class StartButtonListener implements Listener {
public void handleEvent(Event event) {
onStart();
// start detection in separate thread
new Thread() {
public void run() {
configDetector.detectMaxThreads();
onFinish();
}
}.start();
}
}
}

View File

@ -28,9 +28,14 @@ public class GettingStartedDialog extends AbstractModalDialog {
private Button nextButton;
public GettingStartedDialog() {
createShell();
}
@Override
public void open() {
createShell();
super.open();
}
/**
* This method initializes shell
*/

View File

@ -6,6 +6,7 @@
package net.azib.ipscan.gui;
import net.azib.ipscan.config.Config;
import net.azib.ipscan.config.GlobalConfig;
import net.azib.ipscan.config.Labels;
import net.azib.ipscan.config.Version;
import net.azib.ipscan.gui.MainMenu.CommandsMenu;
@ -42,6 +43,7 @@ import org.eclipse.swt.widgets.Shell;
public class MainWindow {
private Shell shell;
private GlobalConfig globalConfig;
private Composite feederArea;
@ -51,7 +53,8 @@ public class MainWindow {
/**
* Creates and initializes the main window.
*/
public MainWindow(Shell shell, Composite feederArea, Composite controlsArea, Combo feederSelectionCombo, Button startStopButton, StartStopScanningAction startStopScanningAction, ResultTable resultTable, StatusBar statusBar, CommandsMenu resultsContextMenu, FeederGUIRegistry feederGUIRegistry) {
public MainWindow(Shell shell, GlobalConfig globalConfig, Composite feederArea, Composite controlsArea, Combo feederSelectionCombo, Button startStopButton, StartStopScanningAction startStopScanningAction, ResultTable resultTable, StatusBar statusBar, CommandsMenu resultsContextMenu, FeederGUIRegistry feederGUIRegistry, ConfigDetectorDialog configDetectorDialog) {
this.globalConfig = globalConfig;
initShell(shell);
@ -71,6 +74,12 @@ public class MainWindow {
// set bounds twice - a workaround for a bug in SWT GTK + Compiz (otherwise window gets smaller and smaller each time)
shell.setBounds(Config.getDimensionsConfig().getWindowBounds());
}
if (globalConfig.isFirstRun) {
configDetectorDialog.open();
new GettingStartedDialog().open();
globalConfig.isFirstRun = false;
}
}
/**
@ -153,7 +162,7 @@ public class MainWindow {
IPFeederSelectionListener feederSelectionListener = new IPFeederSelectionListener();
feederSelectionCombo.addSelectionListener(feederSelectionListener);
// initialize the selected feeder GUI
feederSelectionCombo.select(Config.getGlobal().activeFeeder);
feederSelectionCombo.select(globalConfig.activeFeeder);
feederSelectionCombo.setToolTipText(Labels.getLabel("combobox.feeder.tooltip"));
feederSelectionListener.widgetSelected(null);

View File

@ -24,8 +24,10 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
@ -40,6 +42,7 @@ public class OptionsDialog extends AbstractModalDialog {
private PingerRegistry pingerRegistry;
private GlobalConfig globalConfig;
private ConfigDetectorDialog configDetectorDialog;
private Button okButton;
private Button cancelButton;
@ -67,9 +70,10 @@ public class OptionsDialog extends AbstractModalDialog {
private Button showInfoCheckbox;
private Button askConfirmationCheckbox;
public OptionsDialog(PingerRegistry pingerRegistry, GlobalConfig globalConfig) {
public OptionsDialog(PingerRegistry pingerRegistry, GlobalConfig globalConfig, ConfigDetectorDialog configDetectorDialog) {
this.pingerRegistry = pingerRegistry;
this.globalConfig = globalConfig;
this.configDetectorDialog = configDetectorDialog;
}
@Override
@ -177,8 +181,7 @@ public class OptionsDialog extends AbstractModalDialog {
threadsGroup.setText(Labels.getLabel("options.threads"));
threadsGroup.setLayout(groupLayout);
GridData gridData = new GridData();
gridData.widthHint = 80;
GridData gridData = new GridData(80, SWT.DEFAULT);
Label label;
@ -191,6 +194,11 @@ public class OptionsDialog extends AbstractModalDialog {
label.setText(Labels.getLabel("options.threads.maxThreads"));
maxThreadsText = new Text(threadsGroup, SWT.BORDER);
maxThreadsText.setLayoutData(gridData);
new Label(threadsGroup, SWT.NONE);
Button detectButton = new Button(threadsGroup, SWT.NONE);
detectButton.setText(Labels.getLabel("button.check"));
detectButton.setLayoutData(gridData);
detectButton.addListener(SWT.Selection, new CheckButtonListener());
Group pingingGroup = new Group(scanningTab, SWT.NONE);
pingingGroup.setLayout(groupLayout);
@ -467,4 +475,12 @@ public class OptionsDialog extends AbstractModalDialog {
public void keyReleased(KeyEvent e) {
}
}
class CheckButtonListener implements Listener {
public void handleEvent(Event event) {
globalConfig.maxThreads = Integer.parseInt(maxThreadsText.getText());
configDetectorDialog.open();
loadOptions();
}
}
}

View File

@ -142,7 +142,7 @@ public class RangeFeederGUI extends AbstractFeederGUI {
netmaskCombo.setVisibleItemCount(10);
netmaskCombo.add("/16");
netmaskCombo.add("/24");
netmaskCombo.add("/28");
netmaskCombo.add("/26");
// Warning: IPv4 specific netmasks
netmaskCombo.add("255...192");
netmaskCombo.add("255...128");