mirror of
https://github.com/netchx/netch.git
synced 2026-03-18 18:13:21 +08:00
Fix wait CreateUnicastIP
Fix Guard close file
This commit is contained in:
@@ -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 })
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -6,6 +6,7 @@ ADDRESS_FAMILY
|
||||
MIB_UNICASTIPADDRESS_ROW
|
||||
InitializeUnicastIpAddressEntry
|
||||
CreateUnicastIpAddressEntry
|
||||
GetUnicastIpAddressEntry
|
||||
NotifyUnicastIpAddressChange
|
||||
CancelMibChangeNotify2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user