aboutsummaryrefslogtreecommitdiffstatshomepage
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
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>
-rw-r--r--conf/parser.go15
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs30
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--manager/ipc_server.go35
-rw-r--r--manager/ipc_uapi.go71
-rw-r--r--manager/tunneltracker.go1
7 files changed, 117 insertions, 41 deletions
diff --git a/conf/parser.go b/conf/parser.go
index d26bdea4..dd0ee317 100644
--- a/conf/parser.go
+++ b/conf/parser.go
@@ -6,8 +6,10 @@
package conf
import (
+ "bufio"
"encoding/base64"
"encoding/hex"
+ "io"
"net"
"strconv"
"strings"
@@ -367,8 +369,7 @@ func FromWgQuickWithUnknownEncoding(s string, name string) (*Config, error) {
return nil, firstErr
}
-func FromUAPI(s string, existingConfig *Config) (*Config, error) {
- lines := strings.Split(s, "\n")
+func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) {
parserState := inInterfaceSection
conf := Config{
Name: existingConfig.Name,
@@ -380,9 +381,15 @@ func FromUAPI(s string, existingConfig *Config) (*Config, error) {
},
}
var peer *Peer
- for _, line := range lines {
+ lineReader := bufio.NewReader(reader)
+ for {
+ line, err := lineReader.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ line = line[:len(line)-1]
if len(line) == 0 {
- continue
+ break
}
equals := strings.IndexByte(line, '=')
if equals < 0 {
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
index 13499fcb..50a42c42 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -58,24 +58,25 @@ namespace DemoUI
private void tailTransfer()
{
+ StreamReader reader = null;
NamedPipeClientStream stream = null;
+ while (threadsRunning)
+ {
+ try
+ {
+ stream = Tunnel.Service.GetPipe(configFile);
+ stream.Connect();
+ reader = new StreamReader(stream);
+ break;
+ }
+ catch { }
+ Thread.Sleep(1000);
+ }
+
try
{
while (threadsRunning)
{
- while (threadsRunning)
- {
- try
- {
- stream = Tunnel.Service.GetPipe(configFile);
- stream.Connect();
- break;
- }
- catch { }
- Thread.Sleep(1000);
- }
-
- var reader = new StreamReader(stream);
stream.Write(Encoding.UTF8.GetBytes("get=1\n\n"));
ulong rx = 0, tx = 0;
while (threadsRunning)
@@ -92,14 +93,13 @@ namespace DemoUI
tx += ulong.Parse(line.Substring(9));
}
Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
- stream.Close();
Thread.Sleep(1000);
}
}
catch { }
finally
{
- if (stream != null && stream.IsConnected)
+ if (stream.IsConnected)
stream.Close();
}
}
diff --git a/go.mod b/go.mod
index 92373c4d..20b2d06c 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
golang.org/x/text v0.3.5
- golang.zx2c4.com/wireguard v0.0.20201119-0.20210120232502-fcc8ad05df75
+ golang.zx2c4.com/wireguard v0.0.20201119-0.20210125194828-18e47795e598
)
replace (
diff --git a/go.sum b/go.sum
index 6ec53d78..b3f0f5b8 100644
--- a/go.sum
+++ b/go.sum
@@ -19,8 +19,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.zx2c4.com/wireguard v0.0.20201119-0.20210120232502-fcc8ad05df75 h1:Q8bLImgHajG+re7SSJQstC0ySZtGYx2KH6wVg8BG5YU=
-golang.zx2c4.com/wireguard v0.0.20201119-0.20210120232502-fcc8ad05df75/go.mod h1:r0ExowOoGFfDoLDxx+M9SYbNVsoZ0xviLL+K4f2mt+A=
+golang.zx2c4.com/wireguard v0.0.20201119-0.20210125194828-18e47795e598 h1:adinkobWM0mDfoPbr3b13Lwy0+G6pr4dlXmYaY5lbm8=
+golang.zx2c4.com/wireguard v0.0.20201119-0.20210125194828-18e47795e598/go.mod h1:r0ExowOoGFfDoLDxx+M9SYbNVsoZ0xviLL+K4f2mt+A=
golang.zx2c4.com/wireguard/windows v0.0.0-20201107183008-659a4e955570 h1:sbXpfRwl+7YQY72KBuzyacG7ucr6w4OueJiEb7+pvSk=
golang.zx2c4.com/wireguard/windows v0.0.0-20201107183008-659a4e955570/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd h1:kAUzMAITME2MCtrXBaUa9P4tndiXGWO674k9gn6ZR28=
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)
}