2026-08-12 18:20:51 +00:00
|
|
|
using SharpPcap.LibPcap;
|
|
|
|
|
|
|
|
|
|
namespace gatuna_client;
|
|
|
|
|
|
|
|
|
|
public partial class MainForm : Form
|
|
|
|
|
{
|
|
|
|
|
readonly SessionManager _sessions = new();
|
|
|
|
|
readonly ComboBox _deviceBox = new();
|
|
|
|
|
readonly Button _discoverBtn = new();
|
|
|
|
|
readonly ListView _listView = new();
|
|
|
|
|
readonly Label _statusLabel = new();
|
|
|
|
|
TunnelLink? _link;
|
|
|
|
|
|
|
|
|
|
public MainForm()
|
|
|
|
|
{
|
|
|
|
|
Text = "gatuna";
|
|
|
|
|
Width = 520;
|
|
|
|
|
Height = 380;
|
|
|
|
|
FormBorderStyle = FormBorderStyle.FixedSingle;
|
|
|
|
|
MaximizeBox = false;
|
|
|
|
|
MinimizeBox = false;
|
|
|
|
|
StartPosition = FormStartPosition.CenterScreen;
|
|
|
|
|
InitializeComponents();
|
|
|
|
|
|
|
|
|
|
_sessions.Log += msg => this.Invoke(() => _statusLabel.Text = msg);
|
|
|
|
|
_sessions.ManifestReceived += entries => this.Invoke(() => PopulateList(entries));
|
|
|
|
|
|
|
|
|
|
foreach (var d in TunnelLink.ListDevices())
|
2026-08-13 07:54:06 +00:00
|
|
|
{
|
|
|
|
|
var friendly = d.Interface?.FriendlyName ?? "";
|
|
|
|
|
var desc = d.Interface?.Description ?? "";
|
|
|
|
|
var mac = d.MacAddress?.GetAddressBytes();
|
|
|
|
|
var macStr = mac != null
|
|
|
|
|
? string.Join(":", mac.Select(b => b.ToString("X2")))
|
|
|
|
|
: "??-??-??-??-??-??";
|
|
|
|
|
_deviceBox.Items.Add($"{friendly} — {desc} — {macStr}");
|
|
|
|
|
}
|
2026-08-12 18:20:51 +00:00
|
|
|
if (_deviceBox.Items.Count > 0)
|
|
|
|
|
_deviceBox.SelectedIndex = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitializeComponents()
|
|
|
|
|
{
|
2026-08-13 07:54:06 +00:00
|
|
|
const int pad = 12;
|
2026-08-12 18:20:51 +00:00
|
|
|
|
2026-08-13 07:54:06 +00:00
|
|
|
_deviceBox.Left = pad; _deviceBox.Top = 12;
|
|
|
|
|
_deviceBox.Width = ClientSize.Width - pad * 2;
|
|
|
|
|
_deviceBox.DropDownStyle = ComboBoxStyle.DropDownList;
|
2026-08-12 18:20:51 +00:00
|
|
|
Controls.Add(_deviceBox);
|
|
|
|
|
|
|
|
|
|
_discoverBtn.Text = "Discover";
|
2026-08-13 07:54:06 +00:00
|
|
|
_discoverBtn.Left = pad; _discoverBtn.Top = _deviceBox.Bottom + 8;
|
|
|
|
|
_discoverBtn.Width = 80;
|
2026-08-12 18:20:51 +00:00
|
|
|
_discoverBtn.Click += OnDiscover;
|
|
|
|
|
Controls.Add(_discoverBtn);
|
|
|
|
|
|
2026-08-13 07:54:06 +00:00
|
|
|
_listView.Left = pad; _listView.Top = _discoverBtn.Bottom + 8;
|
|
|
|
|
_listView.Width = ClientSize.Width - pad * 2;
|
|
|
|
|
_listView.Height = 220;
|
2026-08-12 18:20:51 +00:00
|
|
|
_listView.View = View.Details;
|
|
|
|
|
_listView.FullRowSelect = true;
|
|
|
|
|
_listView.CheckBoxes = true;
|
|
|
|
|
_listView.Columns.Add("ID", 36);
|
|
|
|
|
_listView.Columns.Add("Proto", 50);
|
|
|
|
|
_listView.Columns.Add("Port", 56);
|
|
|
|
|
_listView.Columns.Add("Label", 160);
|
|
|
|
|
_listView.Columns.Add("Mirror", 70);
|
|
|
|
|
_listView.ItemChecked += OnItemChecked;
|
|
|
|
|
Controls.Add(_listView);
|
|
|
|
|
|
2026-08-13 07:54:06 +00:00
|
|
|
_statusLabel.Left = pad; _statusLabel.Top = _listView.Bottom + 8;
|
|
|
|
|
_statusLabel.Width = ClientSize.Width - pad * 2;
|
|
|
|
|
_statusLabel.AutoEllipsis = true;
|
2026-08-12 18:20:51 +00:00
|
|
|
Controls.Add(_statusLabel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnDiscover(object? s, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (_deviceBox.SelectedIndex < 0)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Select a network adapter first.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_link != null)
|
|
|
|
|
{
|
|
|
|
|
_sessions.StopAll();
|
|
|
|
|
_sessions.DetachLink();
|
|
|
|
|
_link.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var devices = TunnelLink.ListDevices();
|
|
|
|
|
var device = devices[_deviceBox.SelectedIndex];
|
|
|
|
|
_link = new TunnelLink(device);
|
|
|
|
|
_link.Log += msg => this.Invoke(() => _statusLabel.Text = msg);
|
|
|
|
|
_sessions.AttachLink(_link);
|
|
|
|
|
_link.Open();
|
|
|
|
|
_sessions.Discover();
|
|
|
|
|
_statusLabel.Text = "discovering...";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PopulateList(UpstreamEntry[] entries)
|
|
|
|
|
{
|
|
|
|
|
_listView.BeginUpdate();
|
|
|
|
|
_listView.Items.Clear();
|
|
|
|
|
foreach (var up in entries)
|
|
|
|
|
{
|
|
|
|
|
var item = new ListViewItem(up.Id.ToString());
|
|
|
|
|
item.SubItems.Add(up.ProtoName);
|
|
|
|
|
item.SubItems.Add(up.Port.ToString());
|
|
|
|
|
item.SubItems.Add(up.Label ?? "");
|
|
|
|
|
item.SubItems.Add("");
|
|
|
|
|
item.Tag = up;
|
|
|
|
|
_listView.Items.Add(item);
|
|
|
|
|
}
|
|
|
|
|
_listView.EndUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnItemChecked(object? s, ItemCheckedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.Item.Tag is not UpstreamEntry up) return;
|
|
|
|
|
if (e.Item.Checked)
|
|
|
|
|
{
|
|
|
|
|
var port = _sessions.StartListener(up);
|
|
|
|
|
e.Item.SubItems[4].Text = port.ToString();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (int.TryParse(e.Item.SubItems[4].Text, out var port) && port > 0)
|
|
|
|
|
{
|
|
|
|
|
_sessions.StopListener(port);
|
|
|
|
|
e.Item.SubItems[4].Text = "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.CloseReason == CloseReason.UserClosing)
|
|
|
|
|
{
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
Hide();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
base.OnFormClosing(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Shutdown()
|
|
|
|
|
{
|
|
|
|
|
_sessions.Dispose();
|
|
|
|
|
_link?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|