aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-10-08 09:50:54 +0000
committerJason A. Donenfeld <Jason@zx2c4.com>2019-10-31 11:08:27 +0100
commitdc028e94514d5cc0575bf8dd259dcdfffe7f44d4 (patch)
treeff5129102e0c112f5d1f1e24f553b4735b7b8d6a
parentbuild: go 1.13 now passes correct os version to ld (diff)
downloadwireguard-windows-dc028e94514d5cc0575bf8dd259dcdfffe7f44d4.tar.xz
wireguard-windows-dc028e94514d5cc0575bf8dd259dcdfffe7f44d4.zip
embeddable-dll-service: add all functionality to ringlogger
-rw-r--r--embeddable-dll-service/csharp/Program.cs44
-rw-r--r--embeddable-dll-service/csharp/Ringlogger.cs190
2 files changed, 211 insertions, 23 deletions
diff --git a/embeddable-dll-service/csharp/Program.cs b/embeddable-dll-service/csharp/Program.cs
index 27cefdc9..d99e66fd 100644
--- a/embeddable-dll-service/csharp/Program.cs
+++ b/embeddable-dll-service/csharp/Program.cs
@@ -8,19 +8,49 @@ using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Diagnostics;
+using System.Threading;
+using System.Runtime.InteropServices;
namespace Tunnel
{
class Program
{
- static void Main(string[] args)
+
+ [DllImport("kernel32.dll")]
+ private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);
+ private delegate bool SetConsoleCtrlEventHandler(UInt32 signal);
+
+ public static void Main(string[] args)
{
if (args.Length == 2 && args[0] == "/service")
{
Service.Run(args[1]);
return;
}
+
+ var baseDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
+ var configFile = Path.Combine(baseDirectory, "demobox.conf");
+ var logFile = Path.Combine(baseDirectory, "log.bin");
+
+ try { File.Delete(logFile); } catch { }
+ Ringlogger log = new Ringlogger(logFile, "GUI");
+
+ var logPrintingThread = new Thread(() =>
+ {
+ var cursor = Ringlogger.CursorAll;
+ while (Thread.CurrentThread.IsAlive)
+ {
+ var lines = log.FollowFromCursor(ref cursor);
+ foreach (var line in lines)
+ Console.WriteLine(line);
+ Thread.Sleep(300);
+ }
+ });
+ logPrintingThread.Start();
+
+ log.Write("Generating keys");
var keys = Keypair.Generate();
+ log.Write("Exchanging keys with demo server");
var client = new TcpClient("demo.wireguard.com", 42912);
var stream = client.GetStream();
var reader = new StreamReader(stream, Encoding.UTF8);
@@ -37,15 +67,21 @@ namespace Tunnel
if (status != "OK")
throw new InvalidOperationException(String.Format("Server status is {0}", status));
+ SetConsoleCtrlHandler(delegate
+ {
+ Service.Remove(configFile);
+ Environment.Exit(0);
+ return true;
+ }, true);
+
+ log.Write("Writing config file to disk");
var configFileContents = 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);
- var configFile = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "demobox.conf");
File.WriteAllText(configFile, configFileContents);
try
{
Service.Add(configFile);
- Console.WriteLine("=== Press enter to exit ===");
- Console.ReadLine();
+ logPrintingThread.Join();
}
finally
{
diff --git a/embeddable-dll-service/csharp/Ringlogger.cs b/embeddable-dll-service/csharp/Ringlogger.cs
index 711c22e7..c265142c 100644
--- a/embeddable-dll-service/csharp/Ringlogger.cs
+++ b/embeddable-dll-service/csharp/Ringlogger.cs
@@ -7,40 +7,192 @@ using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Text;
+using System.Collections.Generic;
+using System.Threading;
+using System.Runtime.CompilerServices;
namespace Tunnel
{
public class Ringlogger
{
- private readonly MemoryMappedViewAccessor _viewAccessor;
+ private struct UnixTimestamp
+ {
+ private Int64 _ns;
+ public UnixTimestamp(Int64 ns) => _ns = ns;
+ public bool IsEmpty => _ns == 0;
+ public static UnixTimestamp Empty => new UnixTimestamp(0);
+ public static UnixTimestamp Now
+ {
+ get
+ {
+ var now = DateTimeOffset.UtcNow;
+ var ns = (now.Subtract(DateTimeOffset.FromUnixTimeSeconds(0)).Ticks * 100) % 1000000000;
+ return new UnixTimestamp(now.ToUnixTimeSeconds() * 1000000000 + ns);
+ }
+ }
+ public Int64 Nanoseconds => _ns;
+ public override string ToString()
+ {
+ return DateTimeOffset.FromUnixTimeSeconds(_ns / 1000000000).LocalDateTime.ToString("yyyy'-'MM'-'dd HH':'mm':'ss'.'") + ((_ns % 1000000000).ToString() + "00000").Substring(0, 6);
+ }
+ }
+ private struct Line
+ {
+ private const int maxLineLength = 512;
+ private const int offsetTimeNs = 0;
+ private const int offsetLine = 8;
+
+ private readonly MemoryMappedViewAccessor _view;
+ private readonly int _start;
+ public Line(MemoryMappedViewAccessor view, UInt32 index) => (_view, _start) = (view, (int)(Log.HeaderBytes + index * Bytes));
+
+ public static int Bytes => maxLineLength + offsetLine;
+
+ public UnixTimestamp Timestamp
+ {
+ get => new UnixTimestamp(_view.ReadInt64(_start + offsetTimeNs));
+ set => _view.Write(_start + offsetTimeNs, value.Nanoseconds);
+ }
+
+ public string Text
+ {
+ get
+ {
+ var textBytes = new byte[maxLineLength];
+ _view.ReadArray(_start + offsetLine, textBytes, 0, textBytes.Length);
+ var nullByte = Array.IndexOf<byte>(textBytes, 0);
+ if (nullByte <= 0)
+ return null;
+ return Encoding.UTF8.GetString(textBytes, 0, nullByte);
+ }
+ set
+ {
+ if (value == null)
+ {
+ _view.WriteArray(_start + offsetLine, new byte[maxLineLength], 0, maxLineLength);
+ return;
+ }
+ var textBytes = Encoding.UTF8.GetBytes(value);
+ var bytesToWrite = Math.Min(maxLineLength - 1, textBytes.Length);
+ _view.Write(_start + offsetLine + bytesToWrite, (byte)0);
+ _view.WriteArray(_start + offsetLine, textBytes, 0, bytesToWrite);
+ }
+ }
- public Ringlogger(string filename)
+ public override string ToString()
+ {
+ var time = Timestamp;
+ if (time.IsEmpty)
+ return null;
+ var text = Text;
+ if (text == null)
+ return null;
+ return string.Format("{0}: {1}", time, text);
+ }
+ }
+ private struct Log
{
- var file = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
- var mmap = MemoryMappedFile.CreateFromFile(file, null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, false);
- _viewAccessor = mmap.CreateViewAccessor(0, 8 + 2048 * (512 + 8), MemoryMappedFileAccess.Read);
- if (_viewAccessor.ReadUInt32(0) != 0xbadbabe)
- throw new InvalidDataException("The provided file is missing the magic number.");
+ private const UInt32 maxLines = 2048;
+ private const UInt32 magic = 0xbadbabe;
+ private const int offsetMagic = 0;
+ private const int offsetNextIndex = 4;
+ private const int offsetLines = 8;
+
+ private readonly MemoryMappedViewAccessor _view;
+ public Log(MemoryMappedViewAccessor view) => _view = view;
+
+ public static int HeaderBytes => offsetLines;
+ public static int Bytes => (int)(HeaderBytes + Line.Bytes * maxLines);
+
+ public UInt32 ExpectedMagic => magic;
+ public UInt32 Magic
+ {
+ get => _view.ReadUInt32(offsetMagic);
+ set => _view.Write(offsetMagic, value);
+ }
+
+ public UInt32 NextIndex
+ {
+ get => _view.ReadUInt32(offsetNextIndex);
+ set => _view.Write(offsetNextIndex, value);
+ }
+ public unsafe UInt32 InsertNextIndex() => (UInt32)Interlocked.Increment(ref Unsafe.AsRef<Int32>((_view.SafeMemoryMappedViewHandle.DangerousGetHandle() + offsetNextIndex).ToPointer()));
+
+ public UInt32 LineCount => maxLines;
+ public Line this[UInt32 i] => new Line(_view, i % maxLines);
+
+ public void Clear() => _view.WriteArray(0, new byte[Log.Bytes], 0, Log.Bytes);
+ }
+
+ private readonly Log _log;
+ private readonly string _tag;
+
+ public Ringlogger(string filename, string tag)
+ {
+ var file = File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
+ file.SetLength(Log.Bytes);
+ var mmap = MemoryMappedFile.CreateFromFile(file, null, 0, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
+ var view = mmap.CreateViewAccessor(0, Log.Bytes, MemoryMappedFileAccess.ReadWrite);
+ _log = new Log(view);
+ if (_log.Magic != _log.ExpectedMagic)
+ {
+ _log.Clear();
+ _log.Magic = _log.ExpectedMagic;
+ }
+ _tag = tag;
+ }
+
+ public void Write(string line)
+ {
+ var time = UnixTimestamp.Now;
+ var entry = _log[_log.InsertNextIndex() - 1];
+ entry.Timestamp = UnixTimestamp.Empty;
+ entry.Text = null;
+ entry.Text = string.Format("[{0}] {1}", _tag, line.Trim());
+ entry.Timestamp = time;
}
public void WriteTo(TextWriter writer)
{
- var start = _viewAccessor.ReadUInt32(4);
- for (var i = 0; i < 2048; ++i)
+ var start = _log.NextIndex;
+ for (UInt32 i = 0; i < _log.LineCount; ++i)
{
- var lineOffset = 8 + (8 + 512) * ((i + start) % 2048);
- var timeNs = _viewAccessor.ReadInt64(lineOffset);
- if (timeNs == 0)
+ var entry = _log[i + start];
+ if (entry.Timestamp.IsEmpty)
+ continue;
+ var text = entry.ToString();
+ if (text == null)
continue;
- var textBytes = new byte[512];
- _viewAccessor.ReadArray<byte>(lineOffset + 8, textBytes, 0, textBytes.Length);
- var nullByte = Array.IndexOf<byte>(textBytes, 0);
- if (nullByte <= 0)
+ writer.WriteLine(text);
+ }
+ }
+
+ public static readonly UInt32 CursorAll = UInt32.MaxValue;
+ public List<string> FollowFromCursor(ref UInt32 cursor)
+ {
+ var lines = new List<string>((int)_log.LineCount);
+ var i = cursor;
+ var all = cursor == CursorAll;
+ if (all)
+ i = _log.NextIndex;
+ for (UInt32 l = 0; l < _log.LineCount; ++l, ++i)
+ {
+ if (!all && i % _log.LineCount == _log.NextIndex % _log.LineCount)
+ break;
+ var entry = _log[i];
+ if (entry.Timestamp.IsEmpty)
+ {
+ if (all)
+ continue;
+ break;
+ }
+ cursor = (i + 1) % _log.LineCount;
+ var text = entry.ToString();
+ if (text == null)
continue;
- var text = Encoding.UTF8.GetString(textBytes, 0, nullByte);
- var time = DateTimeOffset.FromUnixTimeMilliseconds(timeNs / 1000000).ToString("yyyy'-'MM'-'dd HH':'mm':'ss'.'ffffff");
- writer.WriteLine(String.Format("{0}: {1}", time, text));
+ lines.Add(text);
}
+ return lines;
}
}
}