Files
2022-01-18 09:14:22 +01:00

272 lines
10 KiB
C#

using PortScanner;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Networking.Pages
{
public partial class WF_PortScanner : UserControl
{
// Delegate to report back with one open port
public delegate void ExecuteOnceCallback(int openPort);
// Delegate to report back with one open port (Async)
public delegate void ExecuteOnceAsyncCallback(int port, bool isOpen, bool isCancelled, bool isLast);
// The manager instance
IScannerManagerSingleton smc;
// Cancellation token source for the cancel button
private CancellationTokenSource cts;
// Current mode of operation
private ScannerManagerSingleton.ScanMode currentScanMode;
public WF_PortScanner()
{
InitializeComponent();
this.Load += WF_PortScanner_Load;
}
private void WF_PortScanner_Load(object sender, EventArgs e)
{
// Get the ScannerManagerSingleton instance
smc = ScannerManagerSingleton.Instance;
// Populate the timeout times list box
PopulateTimeoutListBox();
}
private void PopulateTimeoutListBox()
{
// Assign the list to the ComboBox's DataSource property
timeoutComboBox.DataSource = TimeoutListItem.CreateTimeoutListItems();
timeoutComboBox.DisplayMember = "DisplayMember";
timeoutComboBox.ValueMember = "ValueMember";
// Set default value
timeoutComboBox.SelectedValue = 2000;
}
// This method is used as a callback for portscanning - writes to the log box (text box)
public void PortResult(int port, bool isOpen, bool isCancelled, bool isLast)
{
string status;
// The operation has been cancelled by MainWindow
if (isCancelled)
{
status = "Operation cancelled." + Environment.NewLine;
}
// The port is open
else if (isOpen)
{
//status = String.Format("{0}, {1} port {2} is open.{3}", hostnameTextBox.Text, currentScanMode.ToString(), port, Environment.NewLine);
var item = new ListViewItem(new[] { port.ToString(), "Open" });
listview1.Items.Add(item);
}
// The port is closed
else
{
status = String.Format("{0}, {1} port {2} is closed.{3}", hostnameTextBox.Text, currentScanMode.ToString(), port, Environment.NewLine);
}
if (isLast || isCancelled)
ToggleInputs(true);
}
// Checks whether the timeout combo box has user input or not
private bool IsTimeoutComboBoxUserInput()
{
var inputText = timeoutComboBox.Text;
foreach (var displayMemberText in (List<TimeoutListItem>)timeoutComboBox.DataSource)
{
if (displayMemberText.DisplayMember == inputText)
{
// Select the one that's in the box's list to prevent some problems
// This will return because the user input IS in the combo box's DataSource
// However it is still user input and does not have a ValueMember. Exception
// will be thrown.
timeoutComboBox.SelectedItem = displayMemberText;
return false;
}
}
return true;
}
// Executed when the Check Port button is clicked
private void checkPortButton_Click(object sender, EventArgs e)
{
listview1.Items.Clear();
// Get user inputs
string hostname = hostnameTextBox.Text;
if (hostname == "")
{
MessageBox.Show("Please enter a valid hostname.",
"Input Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
hostnameTextBox.Focus();
return;
}
// Check port
int portMin = InputChecker.ParsePort(portTextBoxMin.Text);
if (portMin == -1)
{
MessageBox.Show((portRangeCheckBox.Checked ? "Lower limit of port range" : "Port") + " invalid.",
"Input Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
portTextBoxMin.Focus();
return;
}
// Get scan mode
ScannerManagerSingleton.ScanMode scanMode = ReadScanMode();
// If custom timeout time, verify correct user input
int timeout;
if (IsTimeoutComboBoxUserInput())
{
// If valid, proceed with that input as timeout
timeout = InputChecker.ParseTimeout(timeoutComboBox.Text);
if (timeout == -1)
{
MessageBox.Show("Timeout format: [time], [time]ms or [time] ms.\nTimeout must be between 250 ms and 20000 ms.",
"Timeout Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
else
{
// Else, use the ValueMember of the selected Member
timeout = (int)timeoutComboBox.SelectedValue;
}
// Instantiate CTS
cts = new CancellationTokenSource();
// Simple one port check
if (!portRangeCheckBox.Checked)
{
// The callback for scan result
var callback = new ExecuteOnceAsyncCallback(PortResult);
// Send one check request and toggle user inputs
ToggleInputs(false);
smc.ExecuteOnceAsync(hostname, portMin, timeout, scanMode, callback, cts.Token);
}
// Port range check
else
{
// Verify input
int portMax = InputChecker.ParsePort(portTextBoxMax.Text);
if (portMax == -1)
{
MessageBox.Show("Upper limit of port range invalid.",
"Input Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
portTextBoxMax.Focus();
return;
}
if (portMax < portMin)
{
MessageBox.Show("Port range invalid.",
"Input Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
portTextBoxMax.Focus();
return;
}
// The callback for scan result
var callback = new ExecuteOnceAsyncCallback(PortResult);
// Set status box text
//var connectionText = String.Format("Connecting to {0}, port {1}...{2}", hostname, portMin,
// Environment.NewLine);
//statusTextBox.AppendText(connectionText);
//Logger.Info(connectionText);
// Toggle inputs and begin operation
ToggleInputs(false);
smc.ExecuteRangeAsync(hostname, portMin, portMax, timeout, scanMode,progressBar1, callback, cts.Token);
}
}
// Read scan mode radio button selection
private ScannerManagerSingleton.ScanMode ReadScanMode()
{
if (tcpModeRadioButton.Checked)
{
currentScanMode = ScannerManagerSingleton.ScanMode.TCP;
}
else
{
currentScanMode = ScannerManagerSingleton.ScanMode.UDP;
}
return currentScanMode;
}
private void portRangeCheckBox_CheckedChanged(object sender, EventArgs e)
{
// This enables or disables the max. port input box
if (portRangeCheckBox.Checked)
{
portTextBoxMax.Enabled = true;
}
else
{
portTextBoxMax.Enabled = false;
}
}
// Toggle all inputs
private void ToggleInputs(bool setting)
{
hostnameTextBox.Enabled = setting;
portTextBoxMin.Enabled = setting;
checkPortButton.Enabled = setting;
portTextBoxMax.Enabled = setting;
portRangeCheckBox.Enabled = setting;
// Re-disable the portMax text box
if (!portRangeCheckBox.Checked)
{
portTextBoxMax.Enabled = false;
}
// Set focus to hostnameTextBox
if (setting)
hostnameTextBox.Focus();
}
private void cancelButton_Click(object sender, EventArgs e)
{
// If cts is instantiated (i.e. the scanning operation is in progress, request cancellation
if (cts != null)
{
cts.Cancel();
progressBar1.Value = 0;
}
}
}
}