Fix wait CreateUnicastIP

Fix Guard close file
This commit is contained in:
ChsBuffer
2021-11-11 13:04:38 +08:00
parent 79c4a9d203
commit 4f5e5ab804
4 changed files with 74 additions and 34 deletions

View File

@@ -61,13 +61,6 @@ namespace Netch.Controllers
public Process Instance { get; }
~Guard()
{
_logFileStream?.Dispose();
_logStreamWriter?.Dispose();
Instance.Dispose();
}
protected async Task StartGuardAsync(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
{
State = State.Starting;
@@ -83,8 +76,12 @@ namespace Netch.Controllers
if (RedirectOutput)
{
Task.Run(() => ReadOutput(Instance.StandardOutput)).Forget();
Task.Run(() => ReadOutput(Instance.StandardError)).Forget();
WaitAllReadOutputTaskAsync(new[]
{
ReadOutputAsync(Instance.StandardOutput),
ReadOutputAsync(Instance.StandardError)
})
.Forget();
if (!StartedKeywords.Any())
{
@@ -114,12 +111,21 @@ namespace Netch.Controllers
}
}
private void ReadOutput(TextReader reader)
private async Task WaitAllReadOutputTaskAsync(Task[] tasks)
{
await Task.WhenAll(tasks);
_logStreamWriter?.Close();
_logFileStream?.Close();
Instance.Dispose();
State = State.Stopped;
}
private async Task ReadOutputAsync(TextReader reader)
{
string? line;
while ((line = reader.ReadLine()) != null)
while ((line = await reader.ReadLineAsync()) != null)
{
_logStreamWriter!.WriteLine(line);
await _logStreamWriter!.WriteLineAsync(line);
OnReadNewLine(line);
if (State == State.Starting)
@@ -133,8 +139,6 @@ namespace Netch.Controllers
}
}
}
State = State.Stopped;
}
public virtual async Task StopAsync()
@@ -144,9 +148,6 @@ namespace Netch.Controllers
protected async Task StopGuardAsync()
{
_logStreamWriter?.Close();
_logFileStream?.Close();
try
{
if (Instance is { HasExited: false })

View File

@@ -96,10 +96,14 @@ namespace Netch.Controllers
var tunIndex = _tunNetworkInterface.GetIndex();
_tun = NetRoute.TemplateBuilder(_tunConfig.Gateway, tunIndex);
RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork,
_tunConfig.Address,
(byte)Utils.Utils.SubnetToCidr(_tunConfig.Netmask),
(ulong)tunIndex);
if (!RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork,
_tunConfig.Address,
(byte)Utils.Utils.SubnetToCidr(_tunConfig.Netmask),
(ulong)tunIndex))
{
Log.Error("Create Unicast IP failed");
throw new MessageException("Create Unicast IP failed");
}
await SetupRouteTableAsync();
}

View File

@@ -1,8 +1,11 @@
using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
using Windows.Win32.Foundation;
using Windows.Win32.Networking.WinSock;
using Windows.Win32.NetworkManagement.IpHelper;
using Serilog;
using static Windows.Win32.PInvoke;
namespace Netch.Interops
@@ -40,25 +43,56 @@ namespace Netch.Interops
return false;
}
// Create a Handle to be notified of IP address changes
// https://docs.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-createunicastipaddressentry#remarks
HANDLE handle = default;
using var obj = new Semaphore(1, 1);
void Callback(void* context, MIB_UNICASTIPADDRESS_ROW* row, MIB_NOTIFICATION_TYPE type) => obj.Release(1);
using var obj = new Semaphore(0, 1);
// Use NotifyUnicastIpAddressChange to determine when the address is ready
obj.WaitOne();
NotifyUnicastIpAddressChange((ushort)ADDRESS_FAMILY.AF_INET, Callback, null, new BOOLEAN(), ref handle);
if (CreateUnicastIpAddressEntry(&addr) != 0)
void Callback(void* context, MIB_UNICASTIPADDRESS_ROW* row, MIB_NOTIFICATION_TYPE type)
{
// ignored return state because i feel great
CancelMibChangeNotify2(handle);
return false;
if (type != MIB_NOTIFICATION_TYPE.MibInitialNotification)
{
// TODO pass error
NTSTATUS state;
if ((state = GetUnicastIpAddressEntry(row)) != 0)
{
Log.Error("CreateUnicastIpAddressEntry failed: {0}", state);
return;
}
if (row -> DadState == NL_DAD_STATE.IpDadStatePreferred)
{
try
{
obj.Release();
}
catch (Exception e)
{
// i don't trust win32 api
Log.Error(e, "semaphore disposed");
}
}
}
}
obj.WaitOne();
NotifyUnicastIpAddressChange((ushort)ADDRESS_FAMILY.AF_INET, Callback, null, new BOOLEAN(byte.MaxValue), ref handle);
return true;
try
{
NTSTATUS state;
if ((state = CreateUnicastIpAddressEntry(&addr)) != 0)
{
Log.Error("CreateUnicastIpAddressEntry failed: {0}", state);
return false;
}
obj.WaitOne();
return true;
}
finally
{
CancelMibChangeNotify2(handle);
}
}
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]

View File

@@ -6,6 +6,7 @@ ADDRESS_FAMILY
MIB_UNICASTIPADDRESS_ROW
InitializeUnicastIpAddressEntry
CreateUnicastIpAddressEntry
GetUnicastIpAddressEntry
NotifyUnicastIpAddressChange
CancelMibChangeNotify2