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)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; } } } }