golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 using System; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.IO; 10 using System.Windows.Forms; 11 using System.Threading; 12 using System.IO.Pipes; 13 using System.Diagnostics; 14 using System.Net.Sockets; 15 using System.Security.AccessControl; 16 17 namespace DemoUI 18 { 19 public partial class MainWindow : Form 20 { 21 private static readonly string userDirectory = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "Config"); //TODO: put in Program Files in real code. 22 private static readonly string configFile = Path.Combine(userDirectory, "demobox.conf"); 23 private static readonly string logFile = Path.Combine(userDirectory, "log.bin"); 24 25 private Tunnel.Ringlogger log; 26 private Thread logPrintingThread, transferUpdateThread; 27 private volatile bool threadsRunning; 28 private bool connected; 29 30 public MainWindow() 31 { 32 makeConfigDirectory(); 33 InitializeComponent(); 34 Application.ApplicationExit += Application_ApplicationExit; 35 try { File.Delete(logFile); } catch { } 36 log = new Tunnel.Ringlogger(logFile, "GUI"); 37 logPrintingThread = new Thread(new ThreadStart(tailLog)); 38 transferUpdateThread = new Thread(new ThreadStart(tailTransfer)); 39 } 40 41 private void makeConfigDirectory() 42 { 43 var ds = new DirectorySecurity(); 44 ds.SetSecurityDescriptorSddlForm("O:BAG:BAD:PAI(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)"); 45 FileSystemAclExtensions.CreateDirectory(ds, userDirectory); 46 } 47 48 private void tailLog() 49 { 50 var cursor = Tunnel.Ringlogger.CursorAll; 51 while (threadsRunning) 52 { 53 var lines = log.FollowFromCursor(ref cursor); 54 foreach (var line in lines) 55 logBox.Invoke(new Action<string>(logBox.AppendText), new object[] { line + "\r\n" }); 56 try 57 { 58 Thread.Sleep(300); 59 } 60 catch 61 { 62 break; 63 } 64 } 65 } 66 67 private void tailTransfer() 68 { 69 Tunnel.Driver.Adapter adapter = null; 70 while (threadsRunning) 71 { 72 if (adapter == null) 73 { 74 while (threadsRunning) 75 { 76 try 77 { 78 adapter = Tunnel.Service.GetAdapter(configFile); 79 break; 80 } 81 catch 82 { 83 try 84 { 85 Thread.Sleep(1000); 86 } 87 catch { } 88 } 89 } 90 } 91 if (adapter == null) 92 continue; 93 try 94 { 95 ulong rx = 0, tx = 0; 96 var config = adapter.GetConfiguration(); 97 foreach (var peer in config.Peers) 98 { 99 rx += peer.RxBytes; 100 tx += peer.TxBytes; 101 } 102 Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx }); 103 Thread.Sleep(1000); 104 } 105 catch { adapter = null; } 106 } 107 } 108 109 private void Application_ApplicationExit(object sender, EventArgs e) 110 { 111 Tunnel.Service.Remove(configFile, true); 112 try { File.Delete(logFile); } catch { } 113 try { File.Delete(configFile); } catch { } 114 } 115 116 private void MainWindow_Load(object sender, EventArgs e) 117 { 118 threadsRunning = true; 119 logPrintingThread.Start(); 120 transferUpdateThread.Start(); 121 } 122 123 private void MainWindow_FormClosing(object sender, FormClosingEventArgs e) 124 { 125 threadsRunning = false; 126 logPrintingThread.Interrupt(); 127 transferUpdateThread.Interrupt(); 128 try { logPrintingThread.Join(); } catch { } 129 try { transferUpdateThread.Join(); } catch { } 130 } 131 132 private static string formatBytes(ulong bytes) 133 { 134 decimal d = bytes; 135 string selectedUnit = null; 136 foreach (string unit in new string[] { "B", "KiB", "MiB", "GiB", "TiB" }) 137 { 138 selectedUnit = unit; 139 if (d < 1024) 140 break; 141 d /= 1024; 142 } 143 return string.Format("{0:0.##} {1}", d, selectedUnit); 144 } 145 146 private void updateTransferTitle(ulong rx, ulong tx) 147 { 148 var titleBase = Text; 149 var idx = titleBase.IndexOf(" - "); 150 if (idx != -1) 151 titleBase = titleBase.Substring(0, idx); 152 if (rx == 0 && tx == 0) 153 Text = titleBase; 154 else 155 Text = string.Format("{0} - rx: {1}, tx: {2}", titleBase, formatBytes(rx), formatBytes(tx)); 156 } 157 158 private async Task<string> generateNewConfig() 159 { 160 log.Write("Generating keys"); 161 var keys = Tunnel.Keypair.Generate(); 162 log.Write("Exchanging keys with demo server"); 163 var client = new TcpClient(); 164 await client.ConnectAsync("demo.wireguard.com", 42912); 165 var stream = client.GetStream(); 166 var reader = new StreamReader(stream, Encoding.UTF8); 167 var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n"); 168 await stream.WriteAsync(pubKeyBytes, 0, pubKeyBytes.Length); 169 await stream.FlushAsync(); 170 var ret = (await reader.ReadLineAsync()).Split(':'); 171 client.Close(); 172 var status = ret.Length >= 1 ? ret[0] : ""; 173 var serverPubkey = ret.Length >= 2 ? ret[1] : ""; 174 var serverPort = ret.Length >= 3 ? ret[2] : ""; 175 var internalIP = ret.Length >= 4 ? ret[3] : ""; 176 if (status != "OK") 177 throw new InvalidOperationException(string.Format("Server status is {0}", status)); 178 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); 179 } 180 181 private async void connectButton_Click(object sender, EventArgs e) 182 { 183 if (connected) 184 { 185 connectButton.Enabled = false; 186 await Task.Run(() => 187 { 188 Tunnel.Service.Remove(configFile, true); 189 try { File.Delete(configFile); } catch { } 190 }); 191 updateTransferTitle(0, 0); 192 connectButton.Text = "&Connect"; 193 connectButton.Enabled = true; 194 connected = false; 195 return; 196 } 197 198 connectButton.Enabled = false; 199 try 200 { 201 var config = await generateNewConfig(); 202 await File.WriteAllBytesAsync(configFile, Encoding.UTF8.GetBytes(config)); 203 await Task.Run(() => Tunnel.Service.Add(configFile, true)); 204 connected = true; 205 connectButton.Text = "&Disconnect"; 206 } 207 catch (Exception ex) 208 { 209 log.Write(ex.Message); 210 try { File.Delete(configFile); } catch { } 211 } 212 connectButton.Enabled = true; 213 } 214 } 215 }