1
0
mirror of https://git.zx2c4.com/wireguard-windows synced 2024-11-10 16:59:18 +00:00
wireguard-windows/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
Jason A. Donenfeld 6ed37f30f5 global: bump date
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-01-06 17:28:13 +01:00

216 lines
7.7 KiB
C#

/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.IO.Pipes;
using System.Diagnostics;
using System.Net.Sockets;
using System.Security.AccessControl;
namespace DemoUI
{
public partial class MainWindow : Form
{
private static readonly string userDirectory = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "Config"); //TODO: put in Program Files in real code.
private static readonly string configFile = Path.Combine(userDirectory, "demobox.conf");
private static readonly string logFile = Path.Combine(userDirectory, "log.bin");
private Tunnel.Ringlogger log;
private Thread logPrintingThread, transferUpdateThread;
private volatile bool threadsRunning;
private bool connected;
public MainWindow()
{
makeConfigDirectory();
InitializeComponent();
Application.ApplicationExit += Application_ApplicationExit;
try { File.Delete(logFile); } catch { }
log = new Tunnel.Ringlogger(logFile, "GUI");
logPrintingThread = new Thread(new ThreadStart(tailLog));
transferUpdateThread = new Thread(new ThreadStart(tailTransfer));
}
private void makeConfigDirectory()
{
var ds = new DirectorySecurity();
ds.SetSecurityDescriptorSddlForm("O:BAG:BAD:PAI(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)");
FileSystemAclExtensions.CreateDirectory(ds, userDirectory);
}
private void tailLog()
{
var cursor = Tunnel.Ringlogger.CursorAll;
while (threadsRunning)
{
var lines = log.FollowFromCursor(ref cursor);
foreach (var line in lines)
logBox.Invoke(new Action<string>(logBox.AppendText), new object[] { line + "\r\n" });
try
{
Thread.Sleep(300);
}
catch
{
break;
}
}
}
private void tailTransfer()
{
Tunnel.Driver.Adapter adapter = null;
while (threadsRunning)
{
if (adapter == null)
{
while (threadsRunning)
{
try
{
adapter = Tunnel.Service.GetAdapter(configFile);
break;
}
catch
{
try
{
Thread.Sleep(1000);
}
catch { }
}
}
}
if (adapter == null)
continue;
try
{
ulong rx = 0, tx = 0;
var config = adapter.GetConfiguration();
foreach (var peer in config.Peers)
{
rx += peer.RxBytes;
tx += peer.TxBytes;
}
Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
Thread.Sleep(1000);
}
catch { adapter = null; }
}
}
private void Application_ApplicationExit(object sender, EventArgs e)
{
Tunnel.Service.Remove(configFile, true);
try { File.Delete(logFile); } catch { }
try { File.Delete(configFile); } catch { }
}
private void MainWindow_Load(object sender, EventArgs e)
{
threadsRunning = true;
logPrintingThread.Start();
transferUpdateThread.Start();
}
private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
{
threadsRunning = false;
logPrintingThread.Interrupt();
transferUpdateThread.Interrupt();
try { logPrintingThread.Join(); } catch { }
try { transferUpdateThread.Join(); } catch { }
}
private static string formatBytes(ulong bytes)
{
decimal d = bytes;
string selectedUnit = null;
foreach (string unit in new string[] { "B", "KiB", "MiB", "GiB", "TiB" })
{
selectedUnit = unit;
if (d < 1024)
break;
d /= 1024;
}
return string.Format("{0:0.##} {1}", d, selectedUnit);
}
private void updateTransferTitle(ulong rx, ulong tx)
{
var titleBase = Text;
var idx = titleBase.IndexOf(" - ");
if (idx != -1)
titleBase = titleBase.Substring(0, idx);
if (rx == 0 && tx == 0)
Text = titleBase;
else
Text = string.Format("{0} - rx: {1}, tx: {2}", titleBase, formatBytes(rx), formatBytes(tx));
}
private async Task<string> generateNewConfig()
{
log.Write("Generating keys");
var keys = Tunnel.Keypair.Generate();
log.Write("Exchanging keys with demo server");
var client = new TcpClient();
await client.ConnectAsync("demo.wireguard.com", 42912);
var stream = client.GetStream();
var reader = new StreamReader(stream, Encoding.UTF8);
var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n");
await stream.WriteAsync(pubKeyBytes, 0, pubKeyBytes.Length);
await stream.FlushAsync();
var ret = (await reader.ReadLineAsync()).Split(':');
client.Close();
var status = ret.Length >= 1 ? ret[0] : "";
var serverPubkey = ret.Length >= 2 ? ret[1] : "";
var serverPort = ret.Length >= 3 ? ret[2] : "";
var internalIP = ret.Length >= 4 ? ret[3] : "";
if (status != "OK")
throw new InvalidOperationException(string.Format("Server status is {0}", status));
return string.Format("[Interface]\nPrivateKey = {0}\nAddress = {1}/24\nDNS = 8.8.8.8, 8.8.4.4\n\n[Peer]\nPublicKey = {2}\nEndpoint = demo.wireguard.com:{3}\nAllowedIPs = 0.0.0.0/0\n", keys.Private, internalIP, serverPubkey, serverPort);
}
private async void connectButton_Click(object sender, EventArgs e)
{
if (connected)
{
connectButton.Enabled = false;
await Task.Run(() =>
{
Tunnel.Service.Remove(configFile, true);
try { File.Delete(configFile); } catch { }
});
updateTransferTitle(0, 0);
connectButton.Text = "&Connect";
connectButton.Enabled = true;
connected = false;
return;
}
connectButton.Enabled = false;
try
{
var config = await generateNewConfig();
await File.WriteAllBytesAsync(configFile, Encoding.UTF8.GetBytes(config));
await Task.Run(() => Tunnel.Service.Add(configFile, true));
connected = true;
connectButton.Text = "&Disconnect";
}
catch (Exception ex)
{
log.Write(ex.Message);
try { File.Delete(configFile); } catch { }
}
connectButton.Enabled = true;
}
}
}