aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/manager
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-01-25 21:11:31 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-02-01 16:55:02 +0100
commitb95b36756ebfcdfaab6a403d93bc6514f3a3b2e2 (patch)
treee74ac26517b4c1eae2868d5351bee24746666f7b /manager
parentversion: adjust x/sys/windows type name (diff)
downloadwireguard-windows-b95b36756ebfcdfaab6a403d93bc6514f3a3b2e2.tar.xz
wireguard-windows-b95b36756ebfcdfaab6a403d93bc6514f3a3b2e2.zip
manager: pipeline UAPI requests
This avoids the somewhat expensive pipe setup. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'manager')
-rw-r--r--manager/ipc_server.go35
-rw-r--r--manager/ipc_uapi.go71
-rw-r--r--manager/tunneltracker.go1
3 files changed, 88 insertions, 19 deletions
diff --git a/manager/ipc_server.go b/manager/ipc_server.go
index 19298016..ccdfe85e 100644
--- a/manager/ipc_server.go
+++ b/manager/ipc_server.go
@@ -10,7 +10,6 @@ import (
"encoding/gob"
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"sync"
@@ -20,8 +19,6 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
- "golang.zx2c4.com/wireguard/ipc/winpipe"
-
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
@@ -54,30 +51,30 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
if err != nil {
return nil, err
}
- pipePath, err := services.PipePathOfTunnel(storedConfig.Name)
- if err != nil {
- return nil, err
- }
- localSystem, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
+ pipe, err := connectTunnelServicePipe(tunnelName)
if err != nil {
return nil, err
}
- pipe, err := winpipe.DialPipe(pipePath, nil, localSystem)
- if err != nil {
- return nil, err
- }
- defer pipe.Close()
- pipe.SetWriteDeadline(time.Now().Add(time.Second * 2))
+ pipe.SetDeadline(time.Now().Add(time.Second * 2))
_, err = pipe.Write([]byte("get=1\n\n"))
- if err != nil {
- return nil, err
+ if err == windows.ERROR_NO_DATA {
+ log.Println("IPC pipe closed unexpectedly, so reopening")
+ pipe.Unlock()
+ disconnectTunnelServicePipe(tunnelName)
+ pipe, err = connectTunnelServicePipe(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ pipe.SetDeadline(time.Now().Add(time.Second * 2))
+ _, err = pipe.Write([]byte("get=1\n\n"))
}
- pipe.SetReadDeadline(time.Now().Add(time.Second * 2))
- resp, err := ioutil.ReadAll(pipe)
if err != nil {
+ pipe.Unlock()
+ disconnectTunnelServicePipe(tunnelName)
return nil, err
}
- conf, err := conf.FromUAPI(string(resp), storedConfig)
+ conf, err := conf.FromUAPI(pipe, storedConfig)
+ pipe.Unlock()
if err != nil {
return nil, err
}
diff --git a/manager/ipc_uapi.go b/manager/ipc_uapi.go
new file mode 100644
index 00000000..b339e3ac
--- /dev/null
+++ b/manager/ipc_uapi.go
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "net"
+ "sync"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/ipc/winpipe"
+
+ "golang.zx2c4.com/wireguard/windows/services"
+)
+
+type connectedTunnel struct {
+ net.Conn
+ sync.Mutex
+}
+
+var connectedTunnelServicePipes = make(map[string]*connectedTunnel)
+var connectedTunnelServicePipesLock sync.RWMutex
+
+func connectTunnelServicePipe(tunnelName string) (*connectedTunnel, error) {
+ connectedTunnelServicePipesLock.RLock()
+ pipe, ok := connectedTunnelServicePipes[tunnelName]
+ if ok {
+ pipe.Lock()
+ connectedTunnelServicePipesLock.RUnlock()
+ return pipe, nil
+ }
+ connectedTunnelServicePipesLock.RUnlock()
+ connectedTunnelServicePipesLock.Lock()
+ defer connectedTunnelServicePipesLock.Unlock()
+ pipe, ok = connectedTunnelServicePipes[tunnelName]
+ if ok {
+ pipe.Lock()
+ return pipe, nil
+ }
+ pipePath, err := services.PipePathOfTunnel(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ localSystem, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
+ if err != nil {
+ return nil, err
+ }
+ pipe = &connectedTunnel{}
+ pipe.Conn, err = winpipe.DialPipe(pipePath, nil, localSystem)
+ if err != nil {
+ return nil, err
+ }
+ connectedTunnelServicePipes[tunnelName] = pipe
+ pipe.Lock()
+ return pipe, nil
+}
+
+func disconnectTunnelServicePipe(tunnelName string) {
+ connectedTunnelServicePipesLock.Lock()
+ defer connectedTunnelServicePipesLock.Unlock()
+ pipe, ok := connectedTunnelServicePipes[tunnelName]
+ if !ok {
+ return
+ }
+ pipe.Lock()
+ pipe.Close()
+ delete(connectedTunnelServicePipes, tunnelName)
+ pipe.Unlock()
+}
diff --git a/manager/tunneltracker.go b/manager/tunneltracker.go
index cfd28693..4625a8e8 100644
--- a/manager/tunneltracker.go
+++ b/manager/tunneltracker.go
@@ -273,4 +273,5 @@ func trackTunnelService(tunnelName string, service *mgr.Service) {
IPCServerNotifyTunnelChange(tunnelName, TunnelStopped, fmt.Errorf("Unable to continue monitoring service, so stopping: %w", err))
service.Control(svc.Stop)
}
+ disconnectTunnelServicePipe(tunnelName)
}