tun: windows: Make adapter rename asynchronous

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-03-22 15:57:23 +01:00
parent 41c30a7279
commit 2faf2dcf90
2 changed files with 13 additions and 60 deletions

View file

@ -75,11 +75,18 @@ func CreateTUN(ifname string) (TUNDevice, error) {
return nil, err
}
err = wt.SetInterfaceName(ifname)
if err != nil {
wt.DeleteInterface(0)
return nil, errors.New("Setting interface name failed: " + err.Error())
}
go func() {
retries := retryTimeout * retryRate
for {
err := wt.SetInterfaceName(ifname)
if err != nil && retries > 0 {
time.Sleep(time.Second / retryRate)
retries--
continue
}
return
}
}()
err = wt.FlushInterface()
if err != nil {

View file

@ -297,62 +297,8 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err
// Get network interface. DIF_INSTALLDEVICE returns almost immediately, while the device
// installation continues in the background. It might take a while, before all registry
// keys and values are populated.
getInterface := func() (*Wintun, error) {
// Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key.
keyDev, err := devInfoList.OpenDevRegKey(deviceData, setupapi.DICS_FLAG_GLOBAL, 0, setupapi.DIREG_DRV, registry.READ)
if err != nil {
return nil, errors.New("Device-specific registry key open failed: " + err.Error())
}
defer keyDev.Close()
// Read the NetCfgInstanceId value.
value, err := getRegStringValue(keyDev, "NetCfgInstanceId")
if err != nil {
if errWin, ok := err.(syscall.Errno); ok && errWin == windows.ERROR_FILE_NOT_FOUND {
return nil, err
}
return nil, errors.New("RegQueryStringValue(\"NetCfgInstanceId\") failed: " + err.Error())
}
// Convert to windows.GUID.
ifid, err := guid.FromString(value)
if err != nil {
return nil, fmt.Errorf("NetCfgInstanceId registry value is not a GUID (expected: \"{...}\", provided: %q)", value)
}
wintun := &Wintun{CfgInstanceID: *ifid}
keyNetName := wintun.GetNetRegKeyName()
keyNet, err := registry.OpenKey(registry.LOCAL_MACHINE, keyNetName, registry.QUERY_VALUE)
if err != nil {
if errWin, ok := err.(syscall.Errno); ok && errWin == windows.ERROR_FILE_NOT_FOUND {
return nil, err
}
return nil, errors.New(fmt.Sprintf("RegOpenKeyEx(%q) failed: ", keyNetName) + err.Error())
}
defer keyNet.Close()
// Query the interface name.
_, valueType, err := keyNet.GetValue("Name", nil)
if err != nil {
if errWin, ok := err.(syscall.Errno); ok && errWin == windows.ERROR_FILE_NOT_FOUND {
return nil, err
}
return nil, errors.New("RegQueryValueEx(\"Name\") failed: " + err.Error())
}
switch valueType {
case registry.SZ, registry.EXPAND_SZ:
default:
return nil, fmt.Errorf("Interface name registry value is not REG_SZ or REG_EXPAND_SZ (expected: %v or %v, provided: %v)", registry.SZ, registry.EXPAND_SZ, valueType)
}
// TUN interface is ready. (As much as we need it.)
return wintun, nil
}
for numAttempts := 0; numAttempts < 30; numAttempts++ {
wintun, err = getInterface()
wintun, err = MakeWintun(devInfoList, deviceData)
if err != nil {
if errWin, ok := err.(syscall.Errno); ok && errWin == windows.ERROR_FILE_NOT_FOUND {
// Wait and retry. TODO: Wait for a cancellable event instead.