diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-22 20:18:38 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-22 20:26:57 +0200 |
commit | 2bb661dc7c70420c3e5c97c5fff70f954a4bb5e6 (patch) | |
tree | a4298e53f0956188e78c529a78c4ad0e8a698b7e /tunnel/winipcfg/interface_change_handler.go | |
parent | ui: trade one hack for another in confview (diff) | |
download | wireguard-windows-2bb661dc7c70420c3e5c97c5fff70f954a4bb5e6.tar.xz wireguard-windows-2bb661dc7c70420c3e5c97c5fff70f954a4bb5e6.zip |
winipcfg: import
We'll maintain this as part of the same repo here. Later maybe we'll
push it into x/sys/windows.
Signed-off-by: Simon Rozman <simon@rozman.si>
Signed-off-by: Aleksandar Pesic <peske.nis@gmail.com>
Diffstat (limited to 'tunnel/winipcfg/interface_change_handler.go')
-rw-r--r-- | tunnel/winipcfg/interface_change_handler.go | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/tunnel/winipcfg/interface_change_handler.go b/tunnel/winipcfg/interface_change_handler.go new file mode 100644 index 00000000..6bb8cf2b --- /dev/null +++ b/tunnel/winipcfg/interface_change_handler.go @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package winipcfg + +import ( + "sync" + + "golang.org/x/sys/windows" +) + +// InterfaceChangeCallback structure allows interface change callback handling. +type InterfaceChangeCallback struct { + cb func(notificationType MibNotificationType, iface *MibIPInterfaceRow) +} + +var ( + interfaceChangeMutex = sync.Mutex{} + interfaceChangeCallbacks = make(map[*InterfaceChangeCallback]bool) + interfaceChangeHandle = windows.Handle(0) +) + +// RegisterInterfaceChangeCallback registers a new InterfaceChangeCallback. If this particular callback is already +// registered, the function will silently return. Returned InterfaceChangeCallback.Unregister method should be used +// to unregister. +func RegisterInterfaceChangeCallback(callback func(notificationType MibNotificationType, iface *MibIPInterfaceRow)) (*InterfaceChangeCallback, error) { + cb := &InterfaceChangeCallback{callback} + + interfaceChangeMutex.Lock() + defer interfaceChangeMutex.Unlock() + + interfaceChangeCallbacks[cb] = true + + if interfaceChangeHandle == 0 { + err := notifyIPInterfaceChange(windows.AF_UNSPEC, windows.NewCallback(interfaceChanged), 0, false, &interfaceChangeHandle) + if err != nil { + delete(interfaceChangeCallbacks, cb) + interfaceChangeHandle = 0 + return nil, err + } + } + + return cb, nil +} + +// Unregister unregisters the callback. +func (callback *InterfaceChangeCallback) Unregister() error { + interfaceChangeMutex.Lock() + defer interfaceChangeMutex.Unlock() + + delete(interfaceChangeCallbacks, callback) + + if len(interfaceChangeCallbacks) < 1 && interfaceChangeHandle != 0 { + err := cancelMibChangeNotify2(interfaceChangeHandle) + if err != nil { + return err + } + interfaceChangeHandle = 0 + } + + return nil +} + +func interfaceChanged(callerContext uintptr, row *MibIPInterfaceRow, notificationType MibNotificationType) uintptr { + interfaceChangeMutex.Lock() + for cb := range interfaceChangeCallbacks { + cb.cb(notificationType, row) + } + interfaceChangeMutex.Unlock() + return 0 +} |