(&procMem),
- procMem.cb);
- if(!gotMemory)
- dwError = ::GetLastError();
- }
-
- if(gotMemory)
- {
- qInfo() << "PID" << proc.th32ProcessID
- << processName
- << "- Private mem:" << TraceMemSize{procMem.PrivateUsage}
- << "- Nonpaged pool:" << TraceMemSize{procMem.QuotaNonPagedPoolUsage}
- << "- Paged pool:" << TraceMemSize{procMem.QuotaPagedPoolUsage}
- << "- Working set:" << TraceMemSize{procMem.WorkingSetSize};
- }
- else
- {
- qInfo() << "PID" << proc.th32ProcessID
- << QStringView{proc.szExeFile}
- << "- can't access memory usage -"
- << WinErrTracer{dwError};
- }
- }
- nextProc = ::Process32NextW(procSnapshot.get(), &proc);
- }
-
- DWORD dwError = ::GetLastError();
- if(dwError != ERROR_SUCCESS && dwError != ERROR_NO_MORE_FILES)
- {
- qWarning() << "Unable to enumerate processes:" << WinErrTracer{dwError};
- }
-
- qInfo() << "Found" << clientProcesses << "running client processes";
-}
-
void WinDaemon::wireguardServiceFailed()
{
// If the connection failed after the WG service was started, check whether
diff --git a/daemon/src/win/win_daemon.h b/daemon/src/win/win_daemon.h
index f0583825..e027608f 100644
--- a/daemon/src/win/win_daemon.h
+++ b/daemon/src/win/win_daemon.h
@@ -231,9 +231,6 @@ class WinDaemon : public Daemon, private MessageWnd
// some circumstances.
void checkWintunInstallation();
- // Trace memory usage of client processes.
- void traceClientMemory();
-
public:
// WireguardServiceBackend calls these methods to hint to us to consider
// re-checking the WinTUN installation state.
@@ -330,9 +327,6 @@ class WinDaemon : public Daemon, private MessageWnd
WinAppMonitor _appMonitor;
SubnetBypass _subnetBypass;
-
- // Trace memory usage of client processes periodically
- QTimer _clientMemTraceTimer;
};
#undef g_daemon
diff --git a/daemon/src/wireguardmethod.cpp b/daemon/src/wireguardmethod.cpp
index 5c374c5e..c4aef5af 100644
--- a/daemon/src/wireguardmethod.cpp
+++ b/daemon/src/wireguardmethod.cpp
@@ -662,7 +662,7 @@ unsigned WireguardMethod::determinePosixMtu(const QHostAddress &host)
// Find the MTU for the interface used to reach the remote host.
mtu = findHostMtu(host.toString());
// Default to 1500 if no MTU was found.
- if(!mtu)
+ if(!mtu || mtu > 1500)
mtu = 1500;
// Subtract 80 bytes for encapsulation.
mtu -= 80;
diff --git a/deps/breakpad/client/linux/data/linux-gate-amd.sym b/deps/breakpad/client/linux/data/linux-gate-amd.sym
index e042a5ec..d1daa3ac 100644
--- a/deps/breakpad/client/linux/data/linux-gate-amd.sym
+++ b/deps/breakpad/client/linux/data/linux-gate-amd.sym
@@ -1,3 +1,3 @@
-MODULE Linux x86 B8CFDE93002D54DA1900A40AA1BD67690 linux-gate.so
-PUBLIC 400 0 __kernel_vsyscall
-STACK WIN 4 400 100 1 1 0 0 0 0 0 1
+version https://git-lfs.github.com/spec/v1
+oid sha256:240e0f7005f84106d7ae89d6fd10e4b9b819e1c240328a9cae4a9ee657bac619
+size 132
diff --git a/deps/breakpad/client/linux/data/linux-gate-intel.sym b/deps/breakpad/client/linux/data/linux-gate-intel.sym
index c209c237..38386e37 100644
--- a/deps/breakpad/client/linux/data/linux-gate-intel.sym
+++ b/deps/breakpad/client/linux/data/linux-gate-intel.sym
@@ -1,3 +1,3 @@
-MODULE Linux x86 4FBDA58B5A1DF5A379E3CF19A235EA090 linux-gate.so
-PUBLIC 400 0 __kernel_vsyscall
-STACK WIN 4 400 200 3 3 0 0 0 0 0 1
\ No newline at end of file
+version https://git-lfs.github.com/spec/v1
+oid sha256:bbdd1692c130636975cff06924da20346d41252f540804d95197f89121f9c42b
+size 131
diff --git a/deps/built/linux/arm64/artifacts/libcrypto.so b/deps/built/linux/arm64/artifacts/libcrypto.so
deleted file mode 120000
index 88520eab..00000000
--- a/deps/built/linux/arm64/artifacts/libcrypto.so
+++ /dev/null
@@ -1 +0,0 @@
-libcrypto.so.1.1
\ No newline at end of file
diff --git a/deps/built/linux/arm64/artifacts/libcrypto.so.1.1 b/deps/built/linux/arm64/artifacts/libcrypto.so.1.1
deleted file mode 100755
index ff350c9f..00000000
Binary files a/deps/built/linux/arm64/artifacts/libcrypto.so.1.1 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libssl.so b/deps/built/linux/arm64/artifacts/libssl.so
deleted file mode 120000
index 21a9bcd9..00000000
--- a/deps/built/linux/arm64/artifacts/libssl.so
+++ /dev/null
@@ -1 +0,0 @@
-libssl.so.1.1
\ No newline at end of file
diff --git a/deps/built/linux/arm64/artifacts/libssl.so.1.1 b/deps/built/linux/arm64/artifacts/libssl.so.1.1
deleted file mode 100755
index fc425ece..00000000
Binary files a/deps/built/linux/arm64/artifacts/libssl.so.1.1 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-composite.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-composite.so.0.0.0
deleted file mode 100755
index e87c4bc7..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-composite.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-damage.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-damage.so.0.0.0
deleted file mode 100755
index 59211050..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-damage.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dpms.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-dpms.so.0.0.0
deleted file mode 100755
index 68875751..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-dpms.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri2.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-dri2.so.0.0.0
deleted file mode 100755
index 6ffa2971..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-dri2.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri3.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-dri3.so.0.0.0
deleted file mode 100755
index 5e36f025..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-dri3.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-ewmh.so.2.0.0 b/deps/built/linux/arm64/artifacts/libxcb-ewmh.so.2.0.0
deleted file mode 100755
index 8b2c013a..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-ewmh.so.2.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-glx.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-glx.so.0.0.0
deleted file mode 100755
index 2c8919f8..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-glx.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-icccm.so.4.0.0 b/deps/built/linux/arm64/artifacts/libxcb-icccm.so.4.0.0
deleted file mode 100755
index 30afbc0a..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-icccm.so.4.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-image.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-image.so.0.0.0
deleted file mode 100755
index 4fffe8e0..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-image.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-keysyms.so.1.0.0 b/deps/built/linux/arm64/artifacts/libxcb-keysyms.so.1.0.0
deleted file mode 100755
index bb25c796..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-keysyms.so.1.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-present.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-present.so.0.0.0
deleted file mode 100755
index 05f6c551..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-present.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-randr.so.0.1.0 b/deps/built/linux/arm64/artifacts/libxcb-randr.so.0.1.0
deleted file mode 100755
index d7022995..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-randr.so.0.1.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-record.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-record.so.0.0.0
deleted file mode 100755
index 0c92bd3d..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-record.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render-util.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-render-util.so.0.0.0
deleted file mode 100755
index 1c07639a..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-render-util.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-render.so.0.0.0
deleted file mode 100755
index b59f230f..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-render.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-res.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-res.so.0.0.0
deleted file mode 100755
index 0d5248ff..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-res.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-screensaver.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-screensaver.so.0.0.0
deleted file mode 100755
index 3101835d..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-screensaver.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shape.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-shape.so.0.0.0
deleted file mode 100755
index fd2b8194..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-shape.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shm.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-shm.so.0.0.0
deleted file mode 100755
index c2d8e0e4..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-shm.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-sync.so.1.0.0 b/deps/built/linux/arm64/artifacts/libxcb-sync.so.1.0.0
deleted file mode 100755
index 0a9c5eea..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-sync.so.1.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-util.so.1.0.0 b/deps/built/linux/arm64/artifacts/libxcb-util.so.1.0.0
deleted file mode 100755
index d2ea32e2..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-util.so.1.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xf86dri.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xf86dri.so.0.0.0
deleted file mode 100755
index 3872a1b9..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xf86dri.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xfixes.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xfixes.so.0.0.0
deleted file mode 100755
index e79f8086..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xfixes.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinerama.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xinerama.so.0.0.0
deleted file mode 100755
index 1f32c68f..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xinerama.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinput.so.0.1.0 b/deps/built/linux/arm64/artifacts/libxcb-xinput.so.0.1.0
deleted file mode 100755
index 0970adfd..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xinput.so.0.1.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xkb.so.1.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xkb.so.1.0.0
deleted file mode 100755
index 27ac213c..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xkb.so.1.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xtest.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xtest.so.0.0.0
deleted file mode 100755
index 2d891717..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xtest.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xv.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xv.so.0.0.0
deleted file mode 100755
index 7d9d3bf7..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xv.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xvmc.so.0.0.0 b/deps/built/linux/arm64/artifacts/libxcb-xvmc.so.0.0.0
deleted file mode 100755
index 5e3b56a8..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb-xvmc.so.0.0.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb.so.1.1.0 b/deps/built/linux/arm64/artifacts/libxcb.so.1.1.0
deleted file mode 100755
index b1f80a2c..00000000
Binary files a/deps/built/linux/arm64/artifacts/libxcb.so.1.1.0 and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/pia-hnsd b/deps/built/linux/arm64/artifacts/pia-hnsd
deleted file mode 100755
index 93d58ee4..00000000
Binary files a/deps/built/linux/arm64/artifacts/pia-hnsd and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/pia-openvpn b/deps/built/linux/arm64/artifacts/pia-openvpn
deleted file mode 100755
index d9c74ce2..00000000
--- a/deps/built/linux/arm64/artifacts/pia-openvpn
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9d4ae0cd12608d618d825a5e89fc085411cb9e99c7242e3f6cfcd1f97ce3c5a9
-size 858560
diff --git a/deps/built/linux/arm64/artifacts/pia-ss-local b/deps/built/linux/arm64/artifacts/pia-ss-local
deleted file mode 100755
index b8b9c706..00000000
Binary files a/deps/built/linux/arm64/artifacts/pia-ss-local and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/pia-unbound b/deps/built/linux/arm64/artifacts/pia-unbound
deleted file mode 100755
index f33131f9..00000000
Binary files a/deps/built/linux/arm64/artifacts/pia-unbound and /dev/null differ
diff --git a/deps/built/linux/arm64/artifacts/pia-wireguard-go b/deps/built/linux/arm64/artifacts/pia-wireguard-go
deleted file mode 100755
index cfda572e..00000000
Binary files a/deps/built/linux/arm64/artifacts/pia-wireguard-go and /dev/null differ
diff --git a/deps/built/linux/arm64/libcrypto.so.1.1 b/deps/built/linux/arm64/libcrypto.so.1.1
index fe9b0e6b..2ba9af47 100755
Binary files a/deps/built/linux/arm64/libcrypto.so.1.1 and b/deps/built/linux/arm64/libcrypto.so.1.1 differ
diff --git a/deps/built/linux/arm64/libssl.so.1.1 b/deps/built/linux/arm64/libssl.so.1.1
index 997bd295..369555a4 100755
Binary files a/deps/built/linux/arm64/libssl.so.1.1 and b/deps/built/linux/arm64/libssl.so.1.1 differ
diff --git a/deps/built/linux/arm64/artifacts/libxcb-composite.so b/deps/built/linux/arm64/libxcb-composite.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-composite.so
rename to deps/built/linux/arm64/libxcb-composite.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-composite.so.0 b/deps/built/linux/arm64/libxcb-composite.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-composite.so.0
rename to deps/built/linux/arm64/libxcb-composite.so.0
diff --git a/deps/built/linux/arm64/libxcb-composite.so.0.0.0 b/deps/built/linux/arm64/libxcb-composite.so.0.0.0
new file mode 100755
index 00000000..2b37ced0
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-composite.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:523c871724909e9fe283f1b7a0dbae77b3bc2a65e1b3645fb9375a0c1997e540
+size 29168
diff --git a/deps/built/linux/arm64/artifacts/libxcb-damage.so b/deps/built/linux/arm64/libxcb-damage.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-damage.so
rename to deps/built/linux/arm64/libxcb-damage.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-damage.so.0 b/deps/built/linux/arm64/libxcb-damage.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-damage.so.0
rename to deps/built/linux/arm64/libxcb-damage.so.0
diff --git a/deps/built/linux/arm64/libxcb-damage.so.0.0.0 b/deps/built/linux/arm64/libxcb-damage.so.0.0.0
new file mode 100755
index 00000000..82bedc8b
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-damage.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4478a8c1649f85d324dbf36577466e9e1224f0b8e53a3cb864b26af947fc6230
+size 23968
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dpms.so b/deps/built/linux/arm64/libxcb-dpms.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dpms.so
rename to deps/built/linux/arm64/libxcb-dpms.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dpms.so.0 b/deps/built/linux/arm64/libxcb-dpms.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dpms.so.0
rename to deps/built/linux/arm64/libxcb-dpms.so.0
diff --git a/deps/built/linux/arm64/libxcb-dpms.so.0.0.0 b/deps/built/linux/arm64/libxcb-dpms.so.0.0.0
new file mode 100755
index 00000000..778f999b
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-dpms.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4bef9d48880128744537c5fb0344e9a6619895133e2c718e2120b23b53470b60
+size 26408
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri2.so b/deps/built/linux/arm64/libxcb-dri2.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dri2.so
rename to deps/built/linux/arm64/libxcb-dri2.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri2.so.0 b/deps/built/linux/arm64/libxcb-dri2.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dri2.so.0
rename to deps/built/linux/arm64/libxcb-dri2.so.0
diff --git a/deps/built/linux/arm64/libxcb-dri2.so.0.0.0 b/deps/built/linux/arm64/libxcb-dri2.so.0.0.0
new file mode 100755
index 00000000..a2f79e54
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-dri2.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e3755ee1b85e8c05930bb4206b44d2f3505e35074f60cb891e6f520ff98d1f65
+size 54384
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri3.so b/deps/built/linux/arm64/libxcb-dri3.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dri3.so
rename to deps/built/linux/arm64/libxcb-dri3.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-dri3.so.0 b/deps/built/linux/arm64/libxcb-dri3.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-dri3.so.0
rename to deps/built/linux/arm64/libxcb-dri3.so.0
diff --git a/deps/built/linux/arm64/libxcb-dri3.so.0.0.0 b/deps/built/linux/arm64/libxcb-dri3.so.0.0.0
new file mode 100755
index 00000000..fb6408bc
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-dri3.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:78b00db89f49803602c9b34636e05fc70b17dbe1d060e580a3298040dcf4b56b
+size 47848
diff --git a/deps/built/linux/arm64/artifacts/libxcb-ewmh.so b/deps/built/linux/arm64/libxcb-ewmh.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-ewmh.so
rename to deps/built/linux/arm64/libxcb-ewmh.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-ewmh.so.2 b/deps/built/linux/arm64/libxcb-ewmh.so.2
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-ewmh.so.2
rename to deps/built/linux/arm64/libxcb-ewmh.so.2
diff --git a/deps/built/linux/arm64/libxcb-ewmh.so.2.0.0 b/deps/built/linux/arm64/libxcb-ewmh.so.2.0.0
new file mode 100755
index 00000000..a1b23257
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-ewmh.so.2.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7327d6528b3a51aa6c83fc793866ff4a58e8cbec3fe789f6351b762855308aec
+size 173456
diff --git a/deps/built/linux/arm64/artifacts/libxcb-glx.so b/deps/built/linux/arm64/libxcb-glx.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-glx.so
rename to deps/built/linux/arm64/libxcb-glx.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-glx.so.0 b/deps/built/linux/arm64/libxcb-glx.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-glx.so.0
rename to deps/built/linux/arm64/libxcb-glx.so.0
diff --git a/deps/built/linux/arm64/libxcb-glx.so.0.0.0 b/deps/built/linux/arm64/libxcb-glx.so.0.0.0
new file mode 100755
index 00000000..bb326b25
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-glx.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a0d6bd7ac3affe767c538c7670637e805248c42d4ac0c7497d36acf9ee4da558
+size 369304
diff --git a/deps/built/linux/arm64/artifacts/libxcb-icccm.so b/deps/built/linux/arm64/libxcb-icccm.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-icccm.so
rename to deps/built/linux/arm64/libxcb-icccm.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-icccm.so.4 b/deps/built/linux/arm64/libxcb-icccm.so.4
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-icccm.so.4
rename to deps/built/linux/arm64/libxcb-icccm.so.4
diff --git a/deps/built/linux/arm64/libxcb-icccm.so.4.0.0 b/deps/built/linux/arm64/libxcb-icccm.so.4.0.0
new file mode 100755
index 00000000..bb84c584
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-icccm.so.4.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1ba7678ef321688533fe6708b10d3459aaa9d3015229c82fb71f0c5efe7ec8d8
+size 67232
diff --git a/deps/built/linux/arm64/artifacts/libxcb-image.so b/deps/built/linux/arm64/libxcb-image.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-image.so
rename to deps/built/linux/arm64/libxcb-image.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-image.so.0 b/deps/built/linux/arm64/libxcb-image.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-image.so.0
rename to deps/built/linux/arm64/libxcb-image.so.0
diff --git a/deps/built/linux/arm64/libxcb-image.so.0.0.0 b/deps/built/linux/arm64/libxcb-image.so.0.0.0
new file mode 100755
index 00000000..2f3f858b
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-image.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f3f31d39a83dd23b624111b98d8d825aab3267e31d11f18a4f7490cb9403e852
+size 59880
diff --git a/deps/built/linux/arm64/artifacts/libxcb-keysyms.so b/deps/built/linux/arm64/libxcb-keysyms.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-keysyms.so
rename to deps/built/linux/arm64/libxcb-keysyms.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-keysyms.so.1 b/deps/built/linux/arm64/libxcb-keysyms.so.1
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-keysyms.so.1
rename to deps/built/linux/arm64/libxcb-keysyms.so.1
diff --git a/deps/built/linux/arm64/libxcb-keysyms.so.1.0.0 b/deps/built/linux/arm64/libxcb-keysyms.so.1.0.0
new file mode 100755
index 00000000..ad947a79
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-keysyms.so.1.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5c68760b73f2e9d284c30fe1607dc0c4a53a0e2c6a47158d98e1081a8b6a5ed9
+size 26832
diff --git a/deps/built/linux/arm64/artifacts/libxcb-present.so b/deps/built/linux/arm64/libxcb-present.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-present.so
rename to deps/built/linux/arm64/libxcb-present.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-present.so.0 b/deps/built/linux/arm64/libxcb-present.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-present.so.0
rename to deps/built/linux/arm64/libxcb-present.so.0
diff --git a/deps/built/linux/arm64/libxcb-present.so.0.0.0 b/deps/built/linux/arm64/libxcb-present.so.0.0.0
new file mode 100755
index 00000000..c0d5b108
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-present.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b65b4b38157340bc17c45773f2a263322b765e5b3e1c234dc92fcdae11e6cfb
+size 30864
diff --git a/deps/built/linux/arm64/artifacts/libxcb-randr.so b/deps/built/linux/arm64/libxcb-randr.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-randr.so
rename to deps/built/linux/arm64/libxcb-randr.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-randr.so.0 b/deps/built/linux/arm64/libxcb-randr.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-randr.so.0
rename to deps/built/linux/arm64/libxcb-randr.so.0
diff --git a/deps/built/linux/arm64/libxcb-randr.so.0.1.0 b/deps/built/linux/arm64/libxcb-randr.so.0.1.0
new file mode 100755
index 00000000..22bf3e38
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-randr.so.0.1.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d3ea3320fdcd42b012546d6f7a12f8f5cf56d7726d9ba9a78c605f641003a2a3
+size 208560
diff --git a/deps/built/linux/arm64/artifacts/libxcb-record.so b/deps/built/linux/arm64/libxcb-record.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-record.so
rename to deps/built/linux/arm64/libxcb-record.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-record.so.0 b/deps/built/linux/arm64/libxcb-record.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-record.so.0
rename to deps/built/linux/arm64/libxcb-record.so.0
diff --git a/deps/built/linux/arm64/libxcb-record.so.0.0.0 b/deps/built/linux/arm64/libxcb-record.so.0.0.0
new file mode 100755
index 00000000..1fded1df
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-record.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b36e65a1fe3c9d30d9ea3510e187ae6503003ef597eba4efe5632f0e8e1aacbe
+size 49592
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render-util.so b/deps/built/linux/arm64/libxcb-render-util.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-render-util.so
rename to deps/built/linux/arm64/libxcb-render-util.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render-util.so.0 b/deps/built/linux/arm64/libxcb-render-util.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-render-util.so.0
rename to deps/built/linux/arm64/libxcb-render-util.so.0
diff --git a/deps/built/linux/arm64/libxcb-render-util.so.0.0.0 b/deps/built/linux/arm64/libxcb-render-util.so.0.0.0
new file mode 100755
index 00000000..1cae68ea
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-render-util.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7e77ccd3f8c060d58d368d1941c0b5d8d2ec6bcbea144ca7eb96d7d96b076da7
+size 43592
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render.so b/deps/built/linux/arm64/libxcb-render.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-render.so
rename to deps/built/linux/arm64/libxcb-render.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-render.so.0 b/deps/built/linux/arm64/libxcb-render.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-render.so.0
rename to deps/built/linux/arm64/libxcb-render.so.0
diff --git a/deps/built/linux/arm64/libxcb-render.so.0.0.0 b/deps/built/linux/arm64/libxcb-render.so.0.0.0
new file mode 100755
index 00000000..d96a562d
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-render.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:72e88e8668807b29c6c0d78271987e6a1eec0d52b6a67437f3a35d40e6d6778f
+size 170648
diff --git a/deps/built/linux/arm64/artifacts/libxcb-res.so b/deps/built/linux/arm64/libxcb-res.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-res.so
rename to deps/built/linux/arm64/libxcb-res.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-res.so.0 b/deps/built/linux/arm64/libxcb-res.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-res.so.0
rename to deps/built/linux/arm64/libxcb-res.so.0
diff --git a/deps/built/linux/arm64/libxcb-res.so.0.0.0 b/deps/built/linux/arm64/libxcb-res.so.0.0.0
new file mode 100755
index 00000000..5a24c1db
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-res.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:929682d4a6a78f64aa3807fac22d64ce54ae968e0c1a657b080845c4605b5999
+size 44248
diff --git a/deps/built/linux/arm64/artifacts/libxcb-screensaver.so b/deps/built/linux/arm64/libxcb-screensaver.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-screensaver.so
rename to deps/built/linux/arm64/libxcb-screensaver.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-screensaver.so.0 b/deps/built/linux/arm64/libxcb-screensaver.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-screensaver.so.0
rename to deps/built/linux/arm64/libxcb-screensaver.so.0
diff --git a/deps/built/linux/arm64/libxcb-screensaver.so.0.0.0 b/deps/built/linux/arm64/libxcb-screensaver.so.0.0.0
new file mode 100755
index 00000000..07d1bdcc
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-screensaver.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b762307d3c04c12c9f7cdb1dbac6ec3e2d7e0260fb74f605f6d780ab468c21f1
+size 36448
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shape.so b/deps/built/linux/arm64/libxcb-shape.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-shape.so
rename to deps/built/linux/arm64/libxcb-shape.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shape.so.0 b/deps/built/linux/arm64/libxcb-shape.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-shape.so.0
rename to deps/built/linux/arm64/libxcb-shape.so.0
diff --git a/deps/built/linux/arm64/libxcb-shape.so.0.0.0 b/deps/built/linux/arm64/libxcb-shape.so.0.0.0
new file mode 100755
index 00000000..01a9c9db
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-shape.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d836d81dcd49038abffa82748c6fc520d7075a5c3d6ebf9acef5081efb7960df
+size 36888
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shm.so b/deps/built/linux/arm64/libxcb-shm.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-shm.so
rename to deps/built/linux/arm64/libxcb-shm.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-shm.so.0 b/deps/built/linux/arm64/libxcb-shm.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-shm.so.0
rename to deps/built/linux/arm64/libxcb-shm.so.0
diff --git a/deps/built/linux/arm64/libxcb-shm.so.0.0.0 b/deps/built/linux/arm64/libxcb-shm.so.0.0.0
new file mode 100755
index 00000000..801a3e48
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-shm.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:231f0fe626b443781b1f7e7af226b76edede6fdf086df1c608fdc44c0686c37b
+size 33040
diff --git a/deps/built/linux/arm64/artifacts/libxcb-sync.so b/deps/built/linux/arm64/libxcb-sync.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-sync.so
rename to deps/built/linux/arm64/libxcb-sync.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-sync.so.1 b/deps/built/linux/arm64/libxcb-sync.so.1
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-sync.so.1
rename to deps/built/linux/arm64/libxcb-sync.so.1
diff --git a/deps/built/linux/arm64/libxcb-sync.so.1.0.0 b/deps/built/linux/arm64/libxcb-sync.so.1.0.0
new file mode 100755
index 00000000..e15acf46
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-sync.so.1.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:202bdea08e7a9852c41723ac2ad3992668f694c0ac648da1d99790565f104054
+size 79544
diff --git a/deps/built/linux/arm64/artifacts/libxcb-util.so b/deps/built/linux/arm64/libxcb-util.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-util.so
rename to deps/built/linux/arm64/libxcb-util.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-util.so.1 b/deps/built/linux/arm64/libxcb-util.so.1
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-util.so.1
rename to deps/built/linux/arm64/libxcb-util.so.1
diff --git a/deps/built/linux/arm64/libxcb-util.so.1.0.0 b/deps/built/linux/arm64/libxcb-util.so.1.0.0
new file mode 100755
index 00000000..28439f28
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-util.so.1.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f03cf947f0fe7bb6db1bc062cb6fe406ad40625bce54be35e054c9bcd6d452f1
+size 55888
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xf86dri.so b/deps/built/linux/arm64/libxcb-xf86dri.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xf86dri.so
rename to deps/built/linux/arm64/libxcb-xf86dri.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xf86dri.so.0 b/deps/built/linux/arm64/libxcb-xf86dri.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xf86dri.so.0
rename to deps/built/linux/arm64/libxcb-xf86dri.so.0
diff --git a/deps/built/linux/arm64/libxcb-xf86dri.so.0.0.0 b/deps/built/linux/arm64/libxcb-xf86dri.so.0.0.0
new file mode 100755
index 00000000..a39469e0
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xf86dri.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6fc21c49142ce6e43124390d137decedf04ef158c688db582340f3cf85a7ee3e
+size 48584
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xfixes.so b/deps/built/linux/arm64/libxcb-xfixes.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xfixes.so
rename to deps/built/linux/arm64/libxcb-xfixes.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xfixes.so.0 b/deps/built/linux/arm64/libxcb-xfixes.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xfixes.so.0
rename to deps/built/linux/arm64/libxcb-xfixes.so.0
diff --git a/deps/built/linux/arm64/libxcb-xfixes.so.0.0.0 b/deps/built/linux/arm64/libxcb-xfixes.so.0.0.0
new file mode 100755
index 00000000..0f25e838
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xfixes.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a961e19dbc34e62646c4c1f7e1983873ef491a1602d8686440ab0cf793d8fc38
+size 93640
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinerama.so b/deps/built/linux/arm64/libxcb-xinerama.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xinerama.so
rename to deps/built/linux/arm64/libxcb-xinerama.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinerama.so.0 b/deps/built/linux/arm64/libxcb-xinerama.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xinerama.so.0
rename to deps/built/linux/arm64/libxcb-xinerama.so.0
diff --git a/deps/built/linux/arm64/libxcb-xinerama.so.0.0.0 b/deps/built/linux/arm64/libxcb-xinerama.so.0.0.0
new file mode 100755
index 00000000..156bd5c4
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xinerama.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:40543245632296bd6cd4ca6a7ab74aceb9ae10169c7b7e9b3dcee26deee8f980
+size 28480
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinput.so b/deps/built/linux/arm64/libxcb-xinput.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xinput.so
rename to deps/built/linux/arm64/libxcb-xinput.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xinput.so.0 b/deps/built/linux/arm64/libxcb-xinput.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xinput.so.0
rename to deps/built/linux/arm64/libxcb-xinput.so.0
diff --git a/deps/built/linux/arm64/libxcb-xinput.so.0.1.0 b/deps/built/linux/arm64/libxcb-xinput.so.0.1.0
new file mode 100755
index 00000000..ccfed2e3
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xinput.so.0.1.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7f928fc494ca3ed65ec3228403760678fa6f5068e64993fd5679b6a8b03e4289
+size 500328
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xkb.so b/deps/built/linux/arm64/libxcb-xkb.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xkb.so
rename to deps/built/linux/arm64/libxcb-xkb.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xkb.so.1 b/deps/built/linux/arm64/libxcb-xkb.so.1
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xkb.so.1
rename to deps/built/linux/arm64/libxcb-xkb.so.1
diff --git a/deps/built/linux/arm64/libxcb-xkb.so.1.0.0 b/deps/built/linux/arm64/libxcb-xkb.so.1.0.0
new file mode 100755
index 00000000..d68c6b7b
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xkb.so.1.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:27a29bc95afb25b75daac598856a94bbc86d26a47331c22a450058e3e0b75908
+size 406368
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xtest.so b/deps/built/linux/arm64/libxcb-xtest.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xtest.so
rename to deps/built/linux/arm64/libxcb-xtest.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xtest.so.0 b/deps/built/linux/arm64/libxcb-xtest.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xtest.so.0
rename to deps/built/linux/arm64/libxcb-xtest.so.0
diff --git a/deps/built/linux/arm64/libxcb-xtest.so.0.0.0 b/deps/built/linux/arm64/libxcb-xtest.so.0.0.0
new file mode 100755
index 00000000..fa1bb520
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xtest.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:85b56e121fd4032788bfa5ddca7b03ca680a52c4275d5a95bcd7681469621b02
+size 23160
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xv.so b/deps/built/linux/arm64/libxcb-xv.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xv.so
rename to deps/built/linux/arm64/libxcb-xv.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xv.so.0 b/deps/built/linux/arm64/libxcb-xv.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xv.so.0
rename to deps/built/linux/arm64/libxcb-xv.so.0
diff --git a/deps/built/linux/arm64/libxcb-xv.so.0.0.0 b/deps/built/linux/arm64/libxcb-xv.so.0.0.0
new file mode 100755
index 00000000..6f774346
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xv.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e30a56f595563fbb2b3581e0a579543eca0d878180297f10b94ae2bc62a7ab62
+size 91912
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xvmc.so b/deps/built/linux/arm64/libxcb-xvmc.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xvmc.so
rename to deps/built/linux/arm64/libxcb-xvmc.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb-xvmc.so.0 b/deps/built/linux/arm64/libxcb-xvmc.so.0
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb-xvmc.so.0
rename to deps/built/linux/arm64/libxcb-xvmc.so.0
diff --git a/deps/built/linux/arm64/libxcb-xvmc.so.0.0.0 b/deps/built/linux/arm64/libxcb-xvmc.so.0.0.0
new file mode 100755
index 00000000..4e1fd0e1
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb-xvmc.so.0.0.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:15244a86cd6f74b482a38f60a1756075b7773fd0f76e992b451738242541362e
+size 45984
diff --git a/deps/built/linux/arm64/artifacts/libxcb.so b/deps/built/linux/arm64/libxcb.so
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb.so
rename to deps/built/linux/arm64/libxcb.so
diff --git a/deps/built/linux/arm64/artifacts/libxcb.so.1 b/deps/built/linux/arm64/libxcb.so.1
similarity index 100%
rename from deps/built/linux/arm64/artifacts/libxcb.so.1
rename to deps/built/linux/arm64/libxcb.so.1
diff --git a/deps/built/linux/arm64/libxcb.so.1.1.0 b/deps/built/linux/arm64/libxcb.so.1.1.0
new file mode 100755
index 00000000..5d737b43
--- /dev/null
+++ b/deps/built/linux/arm64/libxcb.so.1.1.0
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7e0d43029c2c1806f8c3d3bbfdb40129db3837412e6f2bc813e1f960ea5a172a
+size 620528
diff --git a/deps/built/linux/arm64/pia-hnsd b/deps/built/linux/arm64/pia-hnsd
index 116f033d..ae715061 100755
Binary files a/deps/built/linux/arm64/pia-hnsd and b/deps/built/linux/arm64/pia-hnsd differ
diff --git a/deps/built/linux/arm64/pia-ss-local b/deps/built/linux/arm64/pia-ss-local
index b8b9c706..7f1842ec 100755
Binary files a/deps/built/linux/arm64/pia-ss-local and b/deps/built/linux/arm64/pia-ss-local differ
diff --git a/deps/built/linux/arm64/pia-unbound b/deps/built/linux/arm64/pia-unbound
index dd8545e2..ee38631f 100755
Binary files a/deps/built/linux/arm64/pia-unbound and b/deps/built/linux/arm64/pia-unbound differ
diff --git a/deps/built/linux/arm64/pia-wireguard-go b/deps/built/linux/arm64/pia-wireguard-go
index 1a814c46..18f12228 100755
Binary files a/deps/built/linux/arm64/pia-wireguard-go and b/deps/built/linux/arm64/pia-wireguard-go differ
diff --git a/deps/built/linux/armhf/libcrypto.so.1.1 b/deps/built/linux/armhf/libcrypto.so.1.1
index 4dc8c4e6..5a032267 100755
Binary files a/deps/built/linux/armhf/libcrypto.so.1.1 and b/deps/built/linux/armhf/libcrypto.so.1.1 differ
diff --git a/deps/built/linux/armhf/libssl.so.1.1 b/deps/built/linux/armhf/libssl.so.1.1
index 6ac6ac57..c7aa16a0 100755
Binary files a/deps/built/linux/armhf/libssl.so.1.1 and b/deps/built/linux/armhf/libssl.so.1.1 differ
diff --git a/deps/built/linux/armhf/libxcb-composite.so.0.0.0 b/deps/built/linux/armhf/libxcb-composite.so.0.0.0
index 5aef1abc..4dbc7e6f 100755
Binary files a/deps/built/linux/armhf/libxcb-composite.so.0.0.0 and b/deps/built/linux/armhf/libxcb-composite.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-damage.so.0.0.0 b/deps/built/linux/armhf/libxcb-damage.so.0.0.0
index b2ca60c9..18de2343 100755
Binary files a/deps/built/linux/armhf/libxcb-damage.so.0.0.0 and b/deps/built/linux/armhf/libxcb-damage.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-dpms.so.0.0.0 b/deps/built/linux/armhf/libxcb-dpms.so.0.0.0
index 13f5769a..46f45055 100755
Binary files a/deps/built/linux/armhf/libxcb-dpms.so.0.0.0 and b/deps/built/linux/armhf/libxcb-dpms.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-dri2.so.0.0.0 b/deps/built/linux/armhf/libxcb-dri2.so.0.0.0
index d323cb79..b96acba6 100755
Binary files a/deps/built/linux/armhf/libxcb-dri2.so.0.0.0 and b/deps/built/linux/armhf/libxcb-dri2.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-dri3.so.0.0.0 b/deps/built/linux/armhf/libxcb-dri3.so.0.0.0
index 4081555e..6ef7737f 100755
Binary files a/deps/built/linux/armhf/libxcb-dri3.so.0.0.0 and b/deps/built/linux/armhf/libxcb-dri3.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-ewmh.so.2.0.0 b/deps/built/linux/armhf/libxcb-ewmh.so.2.0.0
index 82f6a3d6..336bd1a1 100755
Binary files a/deps/built/linux/armhf/libxcb-ewmh.so.2.0.0 and b/deps/built/linux/armhf/libxcb-ewmh.so.2.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-glx.so.0.0.0 b/deps/built/linux/armhf/libxcb-glx.so.0.0.0
index 60d1b5e9..7f40b608 100755
Binary files a/deps/built/linux/armhf/libxcb-glx.so.0.0.0 and b/deps/built/linux/armhf/libxcb-glx.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-icccm.so.4.0.0 b/deps/built/linux/armhf/libxcb-icccm.so.4.0.0
index 00170727..9c10db1d 100755
Binary files a/deps/built/linux/armhf/libxcb-icccm.so.4.0.0 and b/deps/built/linux/armhf/libxcb-icccm.so.4.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-image.so.0.0.0 b/deps/built/linux/armhf/libxcb-image.so.0.0.0
index 482bfefe..0cfeebbb 100755
Binary files a/deps/built/linux/armhf/libxcb-image.so.0.0.0 and b/deps/built/linux/armhf/libxcb-image.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-keysyms.so.1.0.0 b/deps/built/linux/armhf/libxcb-keysyms.so.1.0.0
index 50951709..01a6bd38 100755
Binary files a/deps/built/linux/armhf/libxcb-keysyms.so.1.0.0 and b/deps/built/linux/armhf/libxcb-keysyms.so.1.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-present.so.0.0.0 b/deps/built/linux/armhf/libxcb-present.so.0.0.0
index c8abaaae..8ffd64d7 100755
Binary files a/deps/built/linux/armhf/libxcb-present.so.0.0.0 and b/deps/built/linux/armhf/libxcb-present.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-randr.so.0.1.0 b/deps/built/linux/armhf/libxcb-randr.so.0.1.0
index 71328184..89cde356 100755
Binary files a/deps/built/linux/armhf/libxcb-randr.so.0.1.0 and b/deps/built/linux/armhf/libxcb-randr.so.0.1.0 differ
diff --git a/deps/built/linux/armhf/libxcb-record.so.0.0.0 b/deps/built/linux/armhf/libxcb-record.so.0.0.0
index 63691754..a1f65bd0 100755
Binary files a/deps/built/linux/armhf/libxcb-record.so.0.0.0 and b/deps/built/linux/armhf/libxcb-record.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-render-util.so.0.0.0 b/deps/built/linux/armhf/libxcb-render-util.so.0.0.0
index 2369c6e9..de368a90 100755
Binary files a/deps/built/linux/armhf/libxcb-render-util.so.0.0.0 and b/deps/built/linux/armhf/libxcb-render-util.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-render.so.0.0.0 b/deps/built/linux/armhf/libxcb-render.so.0.0.0
index 4a5698c3..09f41e4d 100755
Binary files a/deps/built/linux/armhf/libxcb-render.so.0.0.0 and b/deps/built/linux/armhf/libxcb-render.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-res.so.0.0.0 b/deps/built/linux/armhf/libxcb-res.so.0.0.0
index cc521342..c969a4aa 100755
Binary files a/deps/built/linux/armhf/libxcb-res.so.0.0.0 and b/deps/built/linux/armhf/libxcb-res.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-screensaver.so.0.0.0 b/deps/built/linux/armhf/libxcb-screensaver.so.0.0.0
index 06ddd34f..d65a6fa0 100755
Binary files a/deps/built/linux/armhf/libxcb-screensaver.so.0.0.0 and b/deps/built/linux/armhf/libxcb-screensaver.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-shape.so.0.0.0 b/deps/built/linux/armhf/libxcb-shape.so.0.0.0
index e3d183c0..5e7c7f23 100755
Binary files a/deps/built/linux/armhf/libxcb-shape.so.0.0.0 and b/deps/built/linux/armhf/libxcb-shape.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-shm.so.0.0.0 b/deps/built/linux/armhf/libxcb-shm.so.0.0.0
index 6f4e4872..73dc62ac 100755
Binary files a/deps/built/linux/armhf/libxcb-shm.so.0.0.0 and b/deps/built/linux/armhf/libxcb-shm.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-sync.so.1.0.0 b/deps/built/linux/armhf/libxcb-sync.so.1.0.0
index d88178e6..d22ab7f4 100755
Binary files a/deps/built/linux/armhf/libxcb-sync.so.1.0.0 and b/deps/built/linux/armhf/libxcb-sync.so.1.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-util.so.1.0.0 b/deps/built/linux/armhf/libxcb-util.so.1.0.0
index d39a494b..6d0474da 100755
Binary files a/deps/built/linux/armhf/libxcb-util.so.1.0.0 and b/deps/built/linux/armhf/libxcb-util.so.1.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xf86dri.so.0.0.0 b/deps/built/linux/armhf/libxcb-xf86dri.so.0.0.0
index 767720cf..9065e26c 100755
Binary files a/deps/built/linux/armhf/libxcb-xf86dri.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xf86dri.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xfixes.so.0.0.0 b/deps/built/linux/armhf/libxcb-xfixes.so.0.0.0
index 77cc5ffc..72712753 100755
Binary files a/deps/built/linux/armhf/libxcb-xfixes.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xfixes.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xinerama.so.0.0.0 b/deps/built/linux/armhf/libxcb-xinerama.so.0.0.0
index 36c5f7db..03c27f83 100755
Binary files a/deps/built/linux/armhf/libxcb-xinerama.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xinerama.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xinput.so.0.1.0 b/deps/built/linux/armhf/libxcb-xinput.so.0.1.0
index ec2dff1b..1480a0d1 100755
Binary files a/deps/built/linux/armhf/libxcb-xinput.so.0.1.0 and b/deps/built/linux/armhf/libxcb-xinput.so.0.1.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xkb.so.1.0.0 b/deps/built/linux/armhf/libxcb-xkb.so.1.0.0
index abc7b697..ed4f8728 100755
Binary files a/deps/built/linux/armhf/libxcb-xkb.so.1.0.0 and b/deps/built/linux/armhf/libxcb-xkb.so.1.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xtest.so.0.0.0 b/deps/built/linux/armhf/libxcb-xtest.so.0.0.0
index be0e18e2..9fb91c1e 100755
Binary files a/deps/built/linux/armhf/libxcb-xtest.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xtest.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xv.so.0.0.0 b/deps/built/linux/armhf/libxcb-xv.so.0.0.0
index 2029d3c0..c8cf5aba 100755
Binary files a/deps/built/linux/armhf/libxcb-xv.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xv.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb-xvmc.so.0.0.0 b/deps/built/linux/armhf/libxcb-xvmc.so.0.0.0
index b03e2311..e220241c 100755
Binary files a/deps/built/linux/armhf/libxcb-xvmc.so.0.0.0 and b/deps/built/linux/armhf/libxcb-xvmc.so.0.0.0 differ
diff --git a/deps/built/linux/armhf/libxcb.so.1.1.0 b/deps/built/linux/armhf/libxcb.so.1.1.0
index 2baacf4b..9a8c96e8 100755
Binary files a/deps/built/linux/armhf/libxcb.so.1.1.0 and b/deps/built/linux/armhf/libxcb.so.1.1.0 differ
diff --git a/deps/built/linux/armhf/pia-hnsd b/deps/built/linux/armhf/pia-hnsd
index afa4dccf..c8f7acc0 100755
Binary files a/deps/built/linux/armhf/pia-hnsd and b/deps/built/linux/armhf/pia-hnsd differ
diff --git a/deps/built/linux/armhf/pia-ss-local b/deps/built/linux/armhf/pia-ss-local
index 0906d9c9..fb8b6119 100755
Binary files a/deps/built/linux/armhf/pia-ss-local and b/deps/built/linux/armhf/pia-ss-local differ
diff --git a/deps/built/linux/armhf/pia-unbound b/deps/built/linux/armhf/pia-unbound
index 580cd225..b8e5d7ec 100755
Binary files a/deps/built/linux/armhf/pia-unbound and b/deps/built/linux/armhf/pia-unbound differ
diff --git a/deps/built/linux/armhf/pia-wireguard-go b/deps/built/linux/armhf/pia-wireguard-go
index 22c44585..d4757820 100755
Binary files a/deps/built/linux/armhf/pia-wireguard-go and b/deps/built/linux/armhf/pia-wireguard-go differ
diff --git a/deps/built/linux/x86_64/libcrypto.so.1.1 b/deps/built/linux/x86_64/libcrypto.so.1.1
index 13773adc..1332a5d7 100755
Binary files a/deps/built/linux/x86_64/libcrypto.so.1.1 and b/deps/built/linux/x86_64/libcrypto.so.1.1 differ
diff --git a/deps/built/linux/x86_64/libssl.so.1.1 b/deps/built/linux/x86_64/libssl.so.1.1
index 51c0a379..f9ae4d72 100755
Binary files a/deps/built/linux/x86_64/libssl.so.1.1 and b/deps/built/linux/x86_64/libssl.so.1.1 differ
diff --git a/deps/built/linux/x86_64/libxcb-composite.so.0.0.0 b/deps/built/linux/x86_64/libxcb-composite.so.0.0.0
index 80bcf384..f079b77b 100755
Binary files a/deps/built/linux/x86_64/libxcb-composite.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-composite.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-damage.so.0.0.0 b/deps/built/linux/x86_64/libxcb-damage.so.0.0.0
index b929fc5c..d1b50ac4 100755
Binary files a/deps/built/linux/x86_64/libxcb-damage.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-damage.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-dpms.so.0.0.0 b/deps/built/linux/x86_64/libxcb-dpms.so.0.0.0
index 213f8d33..583a8152 100755
Binary files a/deps/built/linux/x86_64/libxcb-dpms.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-dpms.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-dri2.so.0.0.0 b/deps/built/linux/x86_64/libxcb-dri2.so.0.0.0
index 06441a25..781b72b0 100755
Binary files a/deps/built/linux/x86_64/libxcb-dri2.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-dri2.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-dri3.so.0.0.0 b/deps/built/linux/x86_64/libxcb-dri3.so.0.0.0
index 5d228310..362ceed5 100755
Binary files a/deps/built/linux/x86_64/libxcb-dri3.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-dri3.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-ewmh.so.2.0.0 b/deps/built/linux/x86_64/libxcb-ewmh.so.2.0.0
index 891fe761..718ecbd9 100755
Binary files a/deps/built/linux/x86_64/libxcb-ewmh.so.2.0.0 and b/deps/built/linux/x86_64/libxcb-ewmh.so.2.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-glx.so.0.0.0 b/deps/built/linux/x86_64/libxcb-glx.so.0.0.0
index aa0629d7..4491ff77 100755
Binary files a/deps/built/linux/x86_64/libxcb-glx.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-glx.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-icccm.so.4.0.0 b/deps/built/linux/x86_64/libxcb-icccm.so.4.0.0
index 6dcd14a6..71890c8b 100755
Binary files a/deps/built/linux/x86_64/libxcb-icccm.so.4.0.0 and b/deps/built/linux/x86_64/libxcb-icccm.so.4.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-image.so.0.0.0 b/deps/built/linux/x86_64/libxcb-image.so.0.0.0
index 67ad2c09..0346a596 100755
Binary files a/deps/built/linux/x86_64/libxcb-image.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-image.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-keysyms.so.1.0.0 b/deps/built/linux/x86_64/libxcb-keysyms.so.1.0.0
index 74caaa65..ef3b43f7 100755
Binary files a/deps/built/linux/x86_64/libxcb-keysyms.so.1.0.0 and b/deps/built/linux/x86_64/libxcb-keysyms.so.1.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-present.so.0.0.0 b/deps/built/linux/x86_64/libxcb-present.so.0.0.0
index 92587dab..8e241f81 100755
Binary files a/deps/built/linux/x86_64/libxcb-present.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-present.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-randr.so.0.1.0 b/deps/built/linux/x86_64/libxcb-randr.so.0.1.0
index 04dad38f..4e58da12 100755
Binary files a/deps/built/linux/x86_64/libxcb-randr.so.0.1.0 and b/deps/built/linux/x86_64/libxcb-randr.so.0.1.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-record.so.0.0.0 b/deps/built/linux/x86_64/libxcb-record.so.0.0.0
index 490acb4d..7be3bd37 100755
Binary files a/deps/built/linux/x86_64/libxcb-record.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-record.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-render-util.so.0.0.0 b/deps/built/linux/x86_64/libxcb-render-util.so.0.0.0
index 954f69eb..03815ed5 100755
Binary files a/deps/built/linux/x86_64/libxcb-render-util.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-render-util.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-render.so.0.0.0 b/deps/built/linux/x86_64/libxcb-render.so.0.0.0
index 8dcf9f09..d3ab92e0 100755
Binary files a/deps/built/linux/x86_64/libxcb-render.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-render.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-res.so.0.0.0 b/deps/built/linux/x86_64/libxcb-res.so.0.0.0
index 647f7434..23c6c877 100755
Binary files a/deps/built/linux/x86_64/libxcb-res.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-res.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-screensaver.so.0.0.0 b/deps/built/linux/x86_64/libxcb-screensaver.so.0.0.0
index 4696bad1..3854ea97 100755
Binary files a/deps/built/linux/x86_64/libxcb-screensaver.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-screensaver.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-shape.so.0.0.0 b/deps/built/linux/x86_64/libxcb-shape.so.0.0.0
index ead6d3c5..3424f3a0 100755
Binary files a/deps/built/linux/x86_64/libxcb-shape.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-shape.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-shm.so.0.0.0 b/deps/built/linux/x86_64/libxcb-shm.so.0.0.0
index 7e54431b..463dce05 100755
Binary files a/deps/built/linux/x86_64/libxcb-shm.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-shm.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-sync.so.1.0.0 b/deps/built/linux/x86_64/libxcb-sync.so.1.0.0
index 22737d31..591aaf9d 100755
Binary files a/deps/built/linux/x86_64/libxcb-sync.so.1.0.0 and b/deps/built/linux/x86_64/libxcb-sync.so.1.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-util.so.1.0.0 b/deps/built/linux/x86_64/libxcb-util.so.1.0.0
index e2de8aac..53a7f8a9 100755
Binary files a/deps/built/linux/x86_64/libxcb-util.so.1.0.0 and b/deps/built/linux/x86_64/libxcb-util.so.1.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xf86dri.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xf86dri.so.0.0.0
index 67f7dd1a..be2f560a 100755
Binary files a/deps/built/linux/x86_64/libxcb-xf86dri.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xf86dri.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xfixes.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xfixes.so.0.0.0
index 74fe5953..39a70816 100755
Binary files a/deps/built/linux/x86_64/libxcb-xfixes.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xfixes.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xinerama.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xinerama.so.0.0.0
index bc570bc9..1fee4598 100755
Binary files a/deps/built/linux/x86_64/libxcb-xinerama.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xinerama.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xinput.so.0.1.0 b/deps/built/linux/x86_64/libxcb-xinput.so.0.1.0
index d0fd1914..a8a48928 100755
Binary files a/deps/built/linux/x86_64/libxcb-xinput.so.0.1.0 and b/deps/built/linux/x86_64/libxcb-xinput.so.0.1.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xkb.so.1.0.0 b/deps/built/linux/x86_64/libxcb-xkb.so.1.0.0
index ad07f33c..41def31e 100755
Binary files a/deps/built/linux/x86_64/libxcb-xkb.so.1.0.0 and b/deps/built/linux/x86_64/libxcb-xkb.so.1.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xtest.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xtest.so.0.0.0
index db8307fa..b3e13f57 100755
Binary files a/deps/built/linux/x86_64/libxcb-xtest.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xtest.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xv.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xv.so.0.0.0
index b75f7a9f..e7350d7d 100755
Binary files a/deps/built/linux/x86_64/libxcb-xv.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xv.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb-xvmc.so.0.0.0 b/deps/built/linux/x86_64/libxcb-xvmc.so.0.0.0
index fb7ec72e..2c793fec 100755
Binary files a/deps/built/linux/x86_64/libxcb-xvmc.so.0.0.0 and b/deps/built/linux/x86_64/libxcb-xvmc.so.0.0.0 differ
diff --git a/deps/built/linux/x86_64/libxcb.so.1.1.0 b/deps/built/linux/x86_64/libxcb.so.1.1.0
index a2d93011..3085995d 100755
Binary files a/deps/built/linux/x86_64/libxcb.so.1.1.0 and b/deps/built/linux/x86_64/libxcb.so.1.1.0 differ
diff --git a/deps/built/linux/x86_64/pia-hnsd b/deps/built/linux/x86_64/pia-hnsd
index bb31a9e0..b9e402f8 100755
Binary files a/deps/built/linux/x86_64/pia-hnsd and b/deps/built/linux/x86_64/pia-hnsd differ
diff --git a/deps/built/linux/x86_64/pia-ss-local b/deps/built/linux/x86_64/pia-ss-local
index 6fa2190c..8dd74f71 100755
Binary files a/deps/built/linux/x86_64/pia-ss-local and b/deps/built/linux/x86_64/pia-ss-local differ
diff --git a/deps/built/linux/x86_64/pia-unbound b/deps/built/linux/x86_64/pia-unbound
index 89865f33..db979fb1 100755
Binary files a/deps/built/linux/x86_64/pia-unbound and b/deps/built/linux/x86_64/pia-unbound differ
diff --git a/deps/built/linux/x86_64/pia-wireguard-go b/deps/built/linux/x86_64/pia-wireguard-go
index db5e77b9..d14d01d5 100755
Binary files a/deps/built/linux/x86_64/pia-wireguard-go and b/deps/built/linux/x86_64/pia-wireguard-go differ
diff --git a/deps/built/mac/x86_64/libcrypto.1.1.dylib b/deps/built/mac/x86_64/libcrypto.1.1.dylib
index 23d34fae..d98299b5 100755
Binary files a/deps/built/mac/x86_64/libcrypto.1.1.dylib and b/deps/built/mac/x86_64/libcrypto.1.1.dylib differ
diff --git a/deps/built/mac/x86_64/libssl.1.1.dylib b/deps/built/mac/x86_64/libssl.1.1.dylib
index e312b44c..27aa6ac4 100755
Binary files a/deps/built/mac/x86_64/libssl.1.1.dylib and b/deps/built/mac/x86_64/libssl.1.1.dylib differ
diff --git a/deps/built/mac/x86_64/pia-hnsd b/deps/built/mac/x86_64/pia-hnsd
index 0a7c486c..b04dfcca 100755
Binary files a/deps/built/mac/x86_64/pia-hnsd and b/deps/built/mac/x86_64/pia-hnsd differ
diff --git a/deps/built/mac/x86_64/pia-ss-local b/deps/built/mac/x86_64/pia-ss-local
index fb097b29..e7719f2f 100755
Binary files a/deps/built/mac/x86_64/pia-ss-local and b/deps/built/mac/x86_64/pia-ss-local differ
diff --git a/deps/built/mac/x86_64/pia-unbound b/deps/built/mac/x86_64/pia-unbound
index c5ab6aa1..6960e2c7 100755
Binary files a/deps/built/mac/x86_64/pia-unbound and b/deps/built/mac/x86_64/pia-unbound differ
diff --git a/deps/built/mac/x86_64/pia-wireguard-go b/deps/built/mac/x86_64/pia-wireguard-go
index ebe2cf20..be154ba8 100755
Binary files a/deps/built/mac/x86_64/pia-wireguard-go and b/deps/built/mac/x86_64/pia-wireguard-go differ
diff --git a/deps/dump_syms/dump_syms_mac b/deps/dump_syms/dump_syms_mac
index b77a849b..6956265f 100755
Binary files a/deps/dump_syms/dump_syms_mac and b/deps/dump_syms/dump_syms_mac differ
diff --git a/extras/icons/pia.icns b/extras/icons/pia.icns
index e052f551..584b3ce4 100644
Binary files a/extras/icons/pia.icns and b/extras/icons/pia.icns differ
diff --git a/extras/installer/linux/installfiles/run-in-terminal.sh b/extras/installer/linux/installfiles/run-in-terminal.sh
index 0bf3c591..6cadcd57 100644
--- a/extras/installer/linux/installfiles/run-in-terminal.sh
+++ b/extras/installer/linux/installfiles/run-in-terminal.sh
@@ -28,6 +28,8 @@ elif [ -x /usr/bin/konsole ]; then
TERMCMD=/usr/bin/konsole
elif [ -x /usr/bin/xterm ]; then
TERMCMD=/usr/bin/xterm
+elif [ -x /usr/bin/xfce4-terminal ]; then
+ TERMCMD=/usr/bin/xfce4-terminal
else
exit 3
fi
diff --git a/extras/installer/linux/linux_installer.sh b/extras/installer/linux/linux_installer.sh
index de92a9a8..e8b12c1c 100755
--- a/extras/installer/linux/linux_installer.sh
+++ b/extras/installer/linux/linux_installer.sh
@@ -225,7 +225,7 @@ function installDependencies() {
function addGroups() {
for group in "$@"; do
- if ! grep -q $group /etc/group; then
+ if ! getent group $group >/dev/null 2>&1; then
sudo groupadd $group || true
echoPass "Added group $group"
fi
@@ -294,7 +294,9 @@ function installPia() {
fi
sudo cp "$root/installfiles/piavpn.desktop" "/usr/share/applications/${brandCode}vpn.desktop"
if hash update-desktop-database 2>/dev/null; then
- sudo update-desktop-database
+ # Silence output from update-desktop-database; it dumps errors for _any_
+ # quirks in installed .desktop files, not just ours.
+ sudo update-desktop-database 2>/dev/null
fi
echoPass "Created desktop entry"
diff --git a/extras/support-tool/components/FileList.qml b/extras/support-tool/components/FileList.qml
index 51ba5320..bec80df3 100644
--- a/extras/support-tool/components/FileList.qml
+++ b/extras/support-tool/components/FileList.qml
@@ -24,8 +24,9 @@ import PIA.ReportHelper 1.0
import QtQuick.Dialogs 1.3
Item {
- height: 320
- ColumnLayout {
+ height: fileListLayout.height
+ Column {
+ id: fileListLayout
width: parent.width
spacing: 0
@@ -55,7 +56,7 @@ Item {
Rectangle {
border.color: "#889099"
height: 30
- Layout.fillWidth: true
+ width: parent.width
Text {
anchors.left: parent.left
anchors.top: parent.top
@@ -86,7 +87,7 @@ Item {
Rectangle {
id: fileListContainer
opacity: 0.8
- Layout.fillWidth: true
+ width: parent.width
height: fileList.height
border.color: "#d7d8d9"
ListView {
diff --git a/extras/support-tool/components/PayloadInfo.qml b/extras/support-tool/components/PayloadInfo.qml
index 9f8a868d..fc8d892a 100644
--- a/extras/support-tool/components/PayloadInfo.qml
+++ b/extras/support-tool/components/PayloadInfo.qml
@@ -28,30 +28,34 @@ Item {
anchors.margins: 2
anchors.rightMargin: 10
contentWidth: width
+ contentHeight: infoContents.height
clip: true
+ Flickable {
+ anchors.fill: parent
+ // Disable bouncy overscroll, which is a bizarre default for desktop
+ // platforms
+ boundsBehavior: Flickable.StopAtBounds
- ColumnLayout {
- id: infoContents
- width: parent.width
- Text {
- visible: params.mode == "logs"
- text: "" + ReportHelper.getBrandParam("brandName") + " will upload debug logs and some information about your network setup. This information doesn't contain any information about your internet usage.
"
- wrapMode: Text.Wrap
- Layout.fillWidth: true
- Layout.topMargin: 10
- }
- Text {
- visible: params.mode == "crash"
- text: "Please re-start the application. If problem persists, please contact support.
If you have a killswitch enabled your internet might not be accessible. Restarting the application should correct this.
"
- wrapMode: Text.Wrap
- Layout.fillWidth: true
- Layout.topMargin: 10
- }
- FileList {
- Layout.rightMargin: 20
- Layout.topMargin: 10
- Layout.fillWidth: true
+ Column {
+ id: infoContents
+ width: parent.width - 20
+ spacing: 10
+ Text {
+ visible: params.mode == "logs"
+ text: "" + ReportHelper.getBrandParam("brandName") + " will upload debug logs and some information about your network setup. This information doesn't contain any information about your internet usage.
"
+ wrapMode: Text.Wrap
+ width: parent.width
+ }
+ Text {
+ visible: params.mode == "crash"
+ text: "Please re-start the application. If problem persists, please contact support.
If you have a killswitch enabled your internet might not be accessible. Restarting the application should correct this.
"
+ wrapMode: Text.Wrap
+ width: parent.width
+ }
+ FileList {
+ width: parent.width
+ }
}
}
}
diff --git a/extras/support-tool/payloadbuilder.cpp b/extras/support-tool/payloadbuilder.cpp
index 86460959..8a14aabd 100644
--- a/extras/support-tool/payloadbuilder.cpp
+++ b/extras/support-tool/payloadbuilder.cpp
@@ -140,27 +140,15 @@ void PayloadBuilder::addFile(const QString &fullPath)
void PayloadBuilder::addClientDumpFile(const QString &fullPath)
{
QFileInfo fi(fullPath);
- // For the dump file, there's no way to tell exactly when the crash happened
- // from the dmp file itself.
- // Instead of including a separate manifest containing this meta data, for now
- // we can re-name the file to include the timestamp
-
- //
- // Also, some platforms (like Linux) doesn't always support timestamps on the
- // filesystems. So we include a random string in the filename so
- // there's always a valid filename. The first 5 characters of the filename
- // should be good enough
- addFileToPayload(fullPath, QStringLiteral("client-crash/%1-%2.dmp")
- .arg(fi.fileName().left(5))
- .arg(fi.birthTime().toString(QStringLiteral("yyyy-MM-dd_HH-mm-ss"))));
+ addFileToPayload(fullPath, QStringLiteral("client-crash/%1.dmp")
+ .arg(fi.fileName()));
}
void PayloadBuilder::addDaemonDumpFile(const QString &fullPath)
{
QFileInfo fi(fullPath);
- addFileToPayload(fullPath, QStringLiteral("daemon-crash/%1-%2.dmp")
- .arg(fi.fileName().left(5))
- .arg(fi.birthTime().toString(QStringLiteral("yyyy-MM-dd_HH-mm-ss"))));
+ addFileToPayload(fullPath, QStringLiteral("daemon-crash/%1.dmp")
+ .arg(fi.fileName()));
}
void PayloadBuilder::addFileToPayload(const QString &sourcePath, const QString &targetName)
diff --git a/extras/support-tool/support_tool_main.cpp b/extras/support-tool/support_tool_main.cpp
index 0957b22e..e848f32f 100644
--- a/extras/support-tool/support_tool_main.cpp
+++ b/extras/support-tool/support_tool_main.cpp
@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
Path::initializePostApp();
parser.process(app);
- AppSingleton runGuard(Path::SupportToolExecutable);
+ AppSingleton runGuard;
if(runGuard.isAnotherInstanceRunning() > 0) {
qWarning () << "Exiting because another instance appears to be running";
app.quit();
diff --git a/graphics/alert-icons.zip b/graphics/alert-icons.zip
index 16af91be..6e6dde05 100644
Binary files a/graphics/alert-icons.zip and b/graphics/alert-icons.zip differ
diff --git a/graphics/geo_icons/icons(1).zip b/graphics/geo_icons/icons(1).zip
index 0e7d6cae..78e0fcf5 100644
Binary files a/graphics/geo_icons/icons(1).zip and b/graphics/geo_icons/icons(1).zip differ
diff --git a/graphics/shadows.sketch b/graphics/shadows.sketch
index 27c14562..3653bb9a 100644
Binary files a/graphics/shadows.sketch and b/graphics/shadows.sketch differ
diff --git a/rake/model/build.rb b/rake/model/build.rb
index 731f2365..401ce42f 100644
--- a/rake/model/build.rb
+++ b/rake/model/build.rb
@@ -8,12 +8,12 @@
# and creates a per-component build directory for this component.
class Build
# The major-minor-patch parts of this version
- VersionMMP = [2, 9, 0]
+ VersionMMP = [2, 10, 0]
# The base major-minor-patch version, as a string
VersionBase = "#{VersionMMP[0]}.#{VersionMMP[1]}.#{VersionMMP[2]}"
# The prerelease tags for this build (dot-separated, excluding leading
# dash), or empty string if none
- VersionPrerelease = ''
+ VersionPrerelease = 'beta.1'
# Select a build configuration based on environment variables, or use
# defaults for the host platform if unspecified
diff --git a/rake/product/windows.rb b/rake/product/windows.rb
index 687ff14b..0eb16119 100644
--- a/rake/product/windows.rb
+++ b/rake/product/windows.rb
@@ -322,6 +322,9 @@ def self.defineTools(toolsStage)
Executable.new("#{Build::Brand}-closegui")
.source('tools/closegui')
.install(toolsStage, :bin)
+ Executable.new("win-httpstunnel")
+ .source('tools/win-httpstunnel')
+ .install(toolsStage, :bin)
end
def self.collectSymbols(version, stage, debugSymbols)
diff --git a/tools/win-httpstunnel/win-httpstunnel.cpp b/tools/win-httpstunnel/win-httpstunnel.cpp
new file mode 100644
index 00000000..6db70034
--- /dev/null
+++ b/tools/win-httpstunnel/win-httpstunnel.cpp
@@ -0,0 +1,949 @@
+// Copyright (c) 2021 Private Internet Access, Inc.
+//
+// This file is part of the Private Internet Access Desktop Client.
+//
+// The Private Internet Access Desktop Client is free software: you can
+// redistribute it and/or modify it under the terms of the GNU General Public
+// License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// The Private Internet Access Desktop Client is distributed in the hope that
+// it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with the Private Internet Access Desktop Client. If not, see
+// .
+
+#define WIN32_LEAN_AND_MEAN
+#define SECURITY_WIN32
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#pragma comment(lib, "User32.lib")
+#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "Crypt32.lib")
+#pragma comment(lib, "Secur32.lib")
+
+class Winsock
+{
+public:
+ Winsock(int reqMajor, int reqMinor)
+ {
+ // Major number is in low byte, minor number is in high byte
+ int err = ::WSAStartup(MAKEWORD(reqMinor, reqMajor), &_wsaData);
+ // If it failed, abort, do not call WSACleanup()
+ if(err)
+ throw std::runtime_error{"Winsock 2.2 is required"};
+ // Note that if it returned a lower version than we requested (2.1, etc.),
+ // then we do need to call WSACleanup() even if we reject that version.
+ }
+
+ ~Winsock()
+ {
+ ::WSACleanup();
+ }
+
+private:
+ Winsock(const Winsock &) = delete;
+ Winsock &operator=(const Winsock &) = delete;
+
+public:
+ bool supportsVersion(int supportMajor, int supportMinor)
+ {
+ if(LOBYTE(_wsaData.wVersion) < supportMajor)
+ return false;
+ if(LOBYTE(_wsaData.wVersion) == supportMajor)
+ return HIBYTE(_wsaData.wVersion) >= supportMinor;
+ return true;
+ }
+
+private:
+ WSADATA _wsaData;
+};
+
+class SecurityInterface
+{
+public:
+ SecurityInterface()
+ {
+ _pSecFuncTable = ::InitSecurityInterfaceW();
+ if(!_pSecFuncTable)
+ throw std::runtime_error{"Unable to load SSPI security interface"};
+ // TODO - also check the needed entry points
+ }
+
+ const SecurityFunctionTableW &get() const {return *_pSecFuncTable;}
+private:
+ SecurityFunctionTableW *_pSecFuncTable;
+};
+
+// SSPI handle deleters
+class SspiCredDeleter
+{
+public:
+ void operator()(CredHandle &h){::FreeCredentialsHandle(&h);}
+};
+
+class SspiContextDeleter
+{
+public:
+ SspiContextDeleter(const SecurityInterface &secItf) : _secItf{secItf} {}
+
+public:
+ void operator()(CtxtHandle &h){_secItf.get().DeleteSecurityContext(&h);}
+private:
+ const SecurityInterface &_secItf;
+};
+
+// SSPI object owner. Note that SSPI handles are 128 bits on 64-bit platforms,
+// not just a plain pointer (two ULONG_PTRs in general). Most API functions take a
+// pointer-to-handle as a result.
+//
+// The various SSPI handle types are actually all typedefs of the same underlying
+// opaque handle, but they do require different deleters, so the deleter must be
+// specfieid. (The HandleT actually doesn't matter as a result, but it's helpful
+// for exposition at least.)
+template
+class SspiHandle
+{
+public:
+ SspiHandle(DeleterT del = {}) : _handle{}, _deleter{std::move(del)} {}
+ ~SspiHandle() {clear();}
+
+public:
+ void clear() {_deleter(_handle);}
+ // Not const-correct - most API functions require a non-const pointer
+ // Don't mess with the handle through this :-/ Don't use this to
+ // populate SspiHandle with a new handle; use receive() for that
+ HandleT *get() {return &_handle;}
+ // Receive a handle into the SspiHandle(), used to pass a pointer to an
+ // empty handle to an API that creates and stores it
+ HandleT *receive() {clear(); return get();}
+
+private:
+ HandleT _handle;
+ DeleterT _deleter;
+};
+
+using SspiCredHandle = SspiHandle;
+// SspiCtxtHandle requires a SecurityInterface since the deleter API is
+// part of the package interface
+using SspiCtxtHandle = SspiHandle;
+
+class WinSocket
+{
+public:
+ WinSocket(int af, int type, int protocol)
+ : _socket{INVALID_SOCKET}
+ {
+ _socket = ::socket(af, type, protocol);
+ if(_socket == INVALID_SOCKET)
+ throw std::runtime_error{"Unable to allocate socket"};
+ }
+
+ ~WinSocket()
+ {
+ ::closesocket(_socket);
+ }
+
+private:
+ WinSocket(const WinSocket &) = delete;
+ WinSocket &operator=(const WinSocket &) = delete;
+
+public:
+ int connect(const sockaddr *name, int namelen)
+ {
+ return ::connect(_socket, name, namelen);
+ }
+ int send(const char *buf, int len, int flags)
+ {
+ return ::send(_socket, buf, len, flags);
+ }
+ int recv(char *buf, int len, int flags)
+ {
+ return ::recv(_socket, buf, len, flags);
+ }
+ int eventSelect(WSAEVENT eventHandle, long events)
+ {
+ return ::WSAEventSelect(_socket, eventHandle, events);
+ }
+ int enumNetworkEvents(WSAEVENT eventHandle, WSANETWORKEVENTS *pEvents)
+ {
+ return ::WSAEnumNetworkEvents(_socket, eventHandle, pEvents);
+ }
+
+private:
+ SOCKET _socket;
+};
+
+class WinSocketEvent
+{
+public:
+ WinSocketEvent()
+ : _event{::WSACreateEvent()}
+ {
+ if(_event == WSA_INVALID_EVENT)
+ throw std::runtime_error{"Failed to create Winsock event"};
+ }
+ ~WinSocketEvent()
+ {
+ // Somehow WSACloseEvent() can fail (returns zero), but what could we
+ // even do if it did?
+ ::WSACloseEvent(_event);
+ }
+
+private:
+ WinSocketEvent(const WinSocketEvent &) = delete;
+ WinSocketEvent &operator=(const WinSocketEvent &) = delete;
+
+public:
+ WSAEVENT get() {return _event;}
+ operator WSAEVENT() {return get();}
+
+private:
+ WSAEVENT _event;
+};
+
+class WinError : public std::runtime_error
+{
+public:
+ // GetLastError() and security APIs return DWORD, WSAGetLastError()
+ // returns int. Both work with FormatMessage()
+ WinError(const char *pMsg, int err) : WinError{pMsg, static_cast(err)} {}
+ WinError(const char *pMsg, DWORD err)
+ : std::runtime_error{pMsg}, _err{err}
+ {
+ }
+
+public:
+ DWORD getWinErr() const {return _err;}
+ std::string getWinMsg() const;
+
+private:
+ DWORD _err;
+};
+
+std::string WinError::getWinMsg() const
+{
+ LPSTR errMsg{nullptr};
+
+ auto len = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ nullptr, _err, 0,
+ reinterpret_cast(&errMsg), 0, nullptr);
+ std::string msg{errMsg, len};
+ ::LocalFree(errMsg);
+
+ return msg;
+}
+
+void createClientCredential(const SecurityInterface &secItf, SspiCredHandle &clientCred)
+{
+ SCHANNEL_CRED clientCredSpec{};
+ clientCredSpec.dwVersion = SCHANNEL_CRED_VERSION;
+ // Use the defaults for everything in SCHANNEL_CRED; all fields
+ // support 0 indicating the system defaults. No client cert is
+ // specified.
+ TimeStamp expire{};
+ SECURITY_STATUS err = secItf.get().AcquireCredentialsHandleW(nullptr, UNISP_NAME_W,
+ SECPKG_CRED_OUTBOUND, nullptr, &clientCredSpec, nullptr, nullptr,
+ clientCred.receive(), &expire);
+ if(err != SEC_E_OK)
+ throw WinError{"Unable to obtain credentials handle", err};
+}
+
+void secureHandshake(const SecurityInterface &secItf, SspiCredHandle &clientCred, WinSocket &socket,
+ const char *pProxyHostname, SspiCtxtHandle &secureCtxt,
+ std::vector &receivedData)
+{
+ SecBufferDesc sendBufferDesc{};
+ SecBuffer sendBuffer{};
+ sendBufferDesc.ulVersion = SECBUFFER_VERSION;
+ sendBufferDesc.cBuffers = 1;
+ sendBufferDesc.pBuffers = &sendBuffer;
+ sendBuffer.cbBuffer = 0;
+ sendBuffer.BufferType = SECBUFFER_TOKEN;
+ sendBuffer.pvBuffer = nullptr;
+ DWORD sspiContextFlags{};
+ DWORD sspiRequestFlags{ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR |
+ ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM};
+ DWORD sspiRequiredRetFlags{ISC_RET_CONFIDENTIALITY | ISC_RET_REPLAY_DETECT | ISC_RET_SEQUENCE_DETECT |
+ ISC_RET_STREAM};
+
+ // Convert the host name to UTF-16 - since we've already assumed it's
+ // ASCII by using getaddrinfo(), just widen each char to 16 bits.
+ std::wstring hostnameW;
+ std::size_t hostnameLen{std::strlen(pProxyHostname)};
+ hostnameW.resize(hostnameLen);
+ std::copy(pProxyHostname, pProxyHostname + hostnameLen,
+ hostnameW.data());
+ SECURITY_STATUS err = secItf.get().InitializeSecurityContextW(clientCred.get(), nullptr,
+ hostnameW.data(), sspiRequestFlags, 0, 0, nullptr, 0, secureCtxt.receive(),
+ &sendBufferDesc, &sspiContextFlags, nullptr);
+
+ if(err != SEC_I_CONTINUE_NEEDED)
+ throw WinError{"Unable to initialize security context", err};
+
+ // Send the response to the server if present
+ if(sendBuffer.cbBuffer > 0 && sendBuffer.pvBuffer)
+ {
+ int sent = socket.send(reinterpret_cast(sendBuffer.pvBuffer),
+ sendBuffer.cbBuffer, 0);
+ secItf.get().FreeContextBuffer(sendBuffer.pvBuffer);
+ if(sent != sendBuffer.cbBuffer)
+ throw WinError{"Failed to send context response", ::WSAGetLastError()};
+ }
+
+ // Keep receiving until the handshake is complete
+ receivedData.resize(65536);
+ std::size_t queuedSize{0};
+
+ while(err == SEC_I_CONTINUE_NEEDED || err == SEC_E_INCOMPLETE_MESSAGE)
+ {
+ // Read if we don't have a complete message yet (there's nothing queued,
+ // or SSPI said we don't have a complete message).
+ //
+ // We can skip this if we just completed a step and we already have more
+ // data ready.
+ if(queuedSize == 0 || err == SEC_E_INCOMPLETE_MESSAGE)
+ {
+ int received = socket.recv(receivedData.data() + queuedSize,
+ receivedData.size() - queuedSize, 0);
+ if(received == SOCKET_ERROR || received == 0)
+ throw WinError{"Server disconnected during handshake", ::WSAGetLastError()};
+ queuedSize += received;
+ }
+
+ // Pass the input data to SSPI. Provide it an extra input buffer in case it
+ // does not consume all the data; it will copy the remainder to the extra
+ // buffer.
+ SecBufferDesc inputBufferDesc{};
+ SecBuffer inputBuffers[2];
+ SecBufferDesc outputBufferDesc{};
+ SecBuffer outputBuffer;
+ inputBufferDesc.ulVersion = SECBUFFER_VERSION;
+ inputBufferDesc.cBuffers = 2;
+ inputBufferDesc.pBuffers = inputBuffers;
+ inputBuffers[0].cbBuffer = queuedSize;
+ inputBuffers[0].BufferType = SECBUFFER_TOKEN;
+ inputBuffers[0].pvBuffer = reinterpret_cast(receivedData.data());
+ inputBuffers[1].cbBuffer = 0;
+ inputBuffers[1].BufferType = SECBUFFER_EMPTY;
+ inputBuffers[1].pvBuffer = nullptr;
+ outputBufferDesc.ulVersion = SECBUFFER_VERSION;
+ outputBufferDesc.cBuffers = 1;
+ outputBufferDesc.pBuffers = &outputBuffer;
+ outputBuffer.cbBuffer = 0;
+ outputBuffer.BufferType = SECBUFFER_TOKEN;
+ outputBuffer.pvBuffer = nullptr;
+
+ err = secItf.get().InitializeSecurityContextW(clientCred.get(),
+ secureCtxt.get(), nullptr, sspiRequestFlags, 0, 0, &inputBufferDesc,
+ 0, nullptr, &outputBufferDesc, &sspiContextFlags, nullptr);
+
+ // If any response content was given, send it. This can happen even if the
+ // negotiation fails, such as for an error indication.
+ if(outputBuffer.cbBuffer > 0 && outputBuffer.pvBuffer)
+ {
+ auto sent = socket.send(reinterpret_cast(outputBuffer.pvBuffer), outputBuffer.cbBuffer, 0);
+ secItf.get().FreeContextBuffer(outputBuffer.pvBuffer);
+ if(sent != outputBuffer.cbBuffer)
+ throw WinError{"Failed to send handshake response data to server", ::WSAGetLastError()};
+ }
+
+ // If the message was incomplete, keep the data in receivedData and keep receiving.
+ if(err == SEC_E_INCOMPLETE_MESSAGE)
+ continue;
+
+ // If we processed a message and are continuing or finished, we'll check for extra data.
+ //
+ // Any other codes are not expected; fail the handshake.
+ // Schannel does not use the 'complete' statuses (SEC_I_COMPLETE_NEEDED,
+ // SEC_I_COMPLETE_AND_CONTINUE). We don't support any client credentials at
+ // this layer (SEC_I_INCOMPLETE_CREDENTIALS).
+ if(err != SEC_E_OK && err != SEC_I_CONTINUE_NEEDED)
+ throw WinError{"Server handshake failed", err};
+
+ // Put extra data back in receivedData, or reset it if there is no extra data.
+ if(inputBuffers[1].BufferType == SECBUFFER_EXTRA)
+ {
+ std::copy(receivedData.begin() + queuedSize - inputBuffers[1].cbBuffer,
+ receivedData.begin() + queuedSize, receivedData.begin());
+ queuedSize = inputBuffers[1].cbBuffer;
+ }
+ else
+ queuedSize = 0;
+ }
+
+ // We're done, if the handshake didn't complete successfully, bail.
+ if(err != SEC_E_OK)
+ throw WinError{"Server handshake failed", err};
+
+ // Make sure we actually got the security guarantees we asked for
+ if((sspiContextFlags & sspiRequiredRetFlags) != sspiRequiredRetFlags)
+ throw WinError{"Handshake failed security requirements", err};
+
+ // Resize the vector to indicate how much leftover data there actually were
+ receivedData.resize(queuedSize);
+}
+
+class MsgBuf
+{
+public:
+ MsgBuf(const SecPkgContext_StreamSizes &sizes)
+ : _headerSize{sizes.cbHeader}, _trailerSize{sizes.cbTrailer}
+ {
+ setMsgSize(sizes.cbMaximumMessage);
+ }
+
+public:
+ std::size_t headerSize() const {return _headerSize;}
+ std::size_t msgSize() const {return _data.size() - _headerSize - _trailerSize;}
+ void setMsgSize(std::size_t msgSize) {_data.resize(_headerSize + msgSize + _trailerSize);}
+ std::size_t trailerSize() const {return _trailerSize;}
+
+ char *headerBuf() {return _data.data();}
+ char *msgBuf() {return _data.data() + _headerSize;}
+ char *trailerBuf() {return _data.data() + (_data.size() - _trailerSize);}
+
+private:
+ std::size_t _headerSize;
+ std::size_t _trailerSize;
+ std::vector _data;
+};
+
+template
+void appendMsg(MsgBuf &msg, std::size_t &writePos, const char (&data)[N])
+{
+ std::copy(&data[0], &data[N], msg.msgBuf() + writePos);
+ writePos += N;
+}
+void appendMsg(MsgBuf &msg, std::size_t &writePos, const char *data)
+{
+ auto len = data ? std::strlen(data) : 0;
+ std::copy(data, data + len, msg.msgBuf() + writePos);
+ writePos += len;
+}
+void appendMsg(MsgBuf &msg, std::size_t &writePos, const std::string &data)
+{
+ std::copy(data.begin(), data.end(), msg.msgBuf() + writePos);
+ writePos += data.size();
+}
+
+void syncEncryptSend(const SecurityInterface &secItf, WinSocket &socket,
+ SspiCtxtHandle &secureCtxt, MsgBuf &msg)
+{
+ SecBufferDesc sendBufferDesc;
+ SecBuffer sendBuffers[4]{};
+
+ sendBufferDesc.ulVersion = SECBUFFER_VERSION;
+ sendBufferDesc.cBuffers = 4;
+ sendBufferDesc.pBuffers = sendBuffers;
+
+ sendBuffers[0].cbBuffer = msg.headerSize();
+ sendBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
+ sendBuffers[0].pvBuffer = reinterpret_cast(msg.headerBuf());
+ sendBuffers[1].cbBuffer = msg.msgSize();
+ sendBuffers[1].BufferType = SECBUFFER_DATA;
+ sendBuffers[1].pvBuffer = reinterpret_cast(msg.msgBuf());
+ sendBuffers[2].cbBuffer = msg.trailerSize();
+ sendBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
+ sendBuffers[2].pvBuffer = reinterpret_cast(msg.trailerBuf());
+ sendBuffers[3].BufferType = SECBUFFER_EMPTY;
+
+ SECURITY_STATUS err = secItf.get().EncryptMessage(secureCtxt.get(), 0, &sendBufferDesc, 0);
+
+ auto totalSize = sendBuffers[0].cbBuffer + sendBuffers[1].cbBuffer + sendBuffers[2].cbBuffer;
+ auto sent = socket.send(msg.headerBuf(), totalSize, 0);
+ if(sent != totalSize)
+ throw WinError{"Failed to send data to server", ::WSAGetLastError()};
+}
+
+void syncReceiveDecrypt(const SecurityInterface &secItf, WinSocket &socket,
+ SspiCtxtHandle &secureCtxt, std::vector &buffer,
+ char *(&pMsg), std::size_t &msgLen, char *(&pExtra), std::size_t &extraLen)
+{
+ std::size_t queuedData = buffer.size();
+ buffer.resize(65536);
+ SECURITY_STATUS err{SEC_E_OK};
+
+ pMsg = nullptr;
+ msgLen = 0;
+ pExtra = nullptr;
+ extraLen = 0;
+
+ do
+ {
+ // Skip the recv() the first time around if there's already queued data,
+ // we might already have a full message
+ if(err == SEC_E_INCOMPLETE_MESSAGE || queuedData == 0)
+ {
+ auto received = socket.recv(buffer.data() + queuedData, buffer.size() - queuedData, 0);
+ if(received == SOCKET_ERROR && ::WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ // That's fine, just go on as if we received no data
+ received = 0;
+ }
+ else if(received == 0 || received == SOCKET_ERROR)
+ {
+ std::cerr << "receiver error: " << received << " - " << std::hex << WSAGetLastError() << std::endl;
+ throw WinError{"Server disconnected", ::WSAGetLastError()};
+ }
+ queuedData += received;
+ }
+
+ // Try to decrypt the data
+ SecBufferDesc receiveBufferDesc{};
+ SecBuffer receiveBuffers[4]{};
+ receiveBufferDesc.ulVersion = SECBUFFER_VERSION;
+ receiveBufferDesc.cBuffers = 4;
+ receiveBufferDesc.pBuffers = receiveBuffers;
+ receiveBuffers[0].cbBuffer = queuedData;
+ receiveBuffers[0].BufferType = SECBUFFER_DATA;
+ receiveBuffers[0].pvBuffer = reinterpret_cast(buffer.data());
+ receiveBuffers[1].BufferType = SECBUFFER_EMPTY;
+ receiveBuffers[2].BufferType = SECBUFFER_EMPTY;
+ receiveBuffers[3].BufferType = SECBUFFER_EMPTY;
+
+ err = secItf.get().DecryptMessage(secureCtxt.get(), &receiveBufferDesc, 0, nullptr);
+
+ if(err == SEC_I_CONTEXT_EXPIRED)
+ throw WinError{"Server signaled end of connection", err};
+ // TODO - implement renegotiate
+ if(err == SEC_I_RENEGOTIATE)
+ throw WinError{"Server requested renegotiate; not implemented", err};
+ if(err == SEC_E_OK)
+ {
+ // Find the data and extra data
+ for(std::size_t i=0; i<4 && (!pMsg || !pExtra); ++i)
+ {
+ if(!pMsg && receiveBuffers[i].BufferType == SECBUFFER_DATA)
+ {
+ pMsg = reinterpret_cast(receiveBuffers[i].pvBuffer);
+ msgLen = receiveBuffers[i].cbBuffer;
+ }
+ if(!pExtra && receiveBuffers[i].BufferType == SECBUFFER_EXTRA)
+ {
+ pExtra = reinterpret_cast(receiveBuffers[i].pvBuffer);
+ extraLen = receiveBuffers[i].cbBuffer;
+ }
+ }
+ }
+ else if(err != SEC_E_INCOMPLETE_MESSAGE)
+ throw WinError{"Error decrypting incoming data", err};
+ }
+ while(err == SEC_E_INCOMPLETE_MESSAGE);
+}
+
+void readHttpsConnectResponse(const char *pMsgBegin, const char *pMsgEnd)
+{
+ // Read the status line
+ std::string crLf{"\r\n"};
+ auto pStatusLineEnd = std::search(pMsgBegin, pMsgEnd, crLf.begin(), crLf.end());
+ // If there were no headers, no CRLF is found (the message does not
+ // include the terminating CRLFCRLF), and the entire message is the status
+ // line (pStatusLineEnd == pMsgEnd).
+
+ // Check for the 200 status code. We don't really care about the HTTP
+ // version or status message, so just look for " 200 " instead of
+ // actually splitting on spaces.
+ std::string okStatus{" 200 "};
+ if(std::search(pMsgBegin, pStatusLineEnd, okStatus.begin(), okStatus.end())
+ == pStatusLineEnd)
+ {
+ // Didn't find " 200 ". It's some other result code, or an entirely
+ // malformed response.
+ std::cerr << "Server responded: ";
+ std::cerr.write(pMsgBegin, (pMsgEnd-pMsgBegin));
+ std::cerr << std::endl;
+ std::cerr << std::endl;
+ throw std::runtime_error{"Server rejected HTTP CONNECT"};
+ }
+
+ // Success - go ahead with connection.
+ // Don't even read the remaining headers if there are any, we don't care
+ // about them for HTTP CONNECT.
+}
+
+std::string base64Encode(const char *pData, std::size_t len)
+{
+ const char b64chars[65]{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
+
+ std::string result;
+ std::size_t base64Len{len / 3 * 4};
+ if(len % 3)
+ base64Len += 4;
+ result.resize(base64Len);
+
+ char *pOut = result.data();
+ while(len >= 3)
+ {
+ auto word = static_cast((pData[0] << 16) | (pData[1] << 8) | pData[2]);
+
+ pOut[0] = b64chars[word >> 18];
+ word &= 0x03FFFF;
+ pOut[1] = b64chars[word >> 12];
+ word &= 0x000FFF;
+ pOut[2] = b64chars[word >> 6];
+ word &= 0x00003F;
+ pOut[3] = b64chars[word];
+
+ pData += 3;
+ len -= 3;
+ pOut += 4;
+ }
+
+ // Handle tail bytes and '=' padding. There are only two possibilites -
+ // len=2 (AAA=) and len=1 (AA==)
+ if(len)
+ {
+ auto tail = static_cast(pData[0] << 16);
+ if(len == 2)
+ tail |= (pData[1] << 8);
+
+ pOut[0] = b64chars[tail >> 18];
+ tail &= 0x03FFFF;
+ pOut[1] = b64chars[tail >> 12];
+ tail &= 0x000FFF;
+ if(len == 2)
+ pOut[2] = b64chars[tail >> 6];
+ else
+ pOut[2] = '=';
+ pOut[3] = '=';
+ }
+
+ return result;
+}
+
+class CliParams
+{
+public:
+ CliParams(int argc, char **argv)
+ {
+ if(argc != 5)
+ throw std::runtime_error{"Incorrect number of arguments"};
+
+ _pBasicAuth = argv[1];
+ _pProxyHost = argv[2];
+ const char *proxyPortStr{argv[3]};
+ _pTunnelTarget = argv[4];
+ if(!_pBasicAuth || !_pProxyHost || !proxyPortStr || !_pTunnelTarget)
+ throw std::runtime_error{"Incorrect number of arguments"};
+
+ // Parse proxyPortStr; it must only contain digits and result in a value
+ // in range [1, 65536]. std::atoi() also allows whitespace, +-, etc., so
+ // check digits manually too.
+ for(const char *pPortChar = proxyPortStr; *pPortChar; ++pPortChar)
+ {
+ if(*pPortChar < '0' || *pPortChar > '9')
+ throw std::runtime_error{"Invalid proxy port"};
+ }
+ int parsedPort = std::atoi(proxyPortStr);
+ if(parsedPort < 1 || parsedPort > 65535)
+ throw std::runtime_error{"Invalid proxy port"};
+ _proxyPort = static_cast(parsedPort);
+ }
+
+public:
+ const char *basicAuth() const {return _pBasicAuth;}
+ const char *proxyHost() const {return _pProxyHost;}
+ std::uint16_t proxyPort() const {return _proxyPort;}
+ const char *tunnelTarget() const {return _pTunnelTarget;}
+
+private:
+ const char *_pBasicAuth;
+ const char *_pProxyHost;
+ std::uint16_t _proxyPort;
+ const char *_pTunnelTarget;
+};
+
+void printUsage(const char *name)
+{
+ std::cerr << "usage:" << std::endl;
+ std::cerr << " " << name << " " << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "example:" << std::endl;
+ std::cerr << " " << name << " me:mypassword our.proxy.example.com 8443 internal.service.example.com:22" << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "Creates a tunneled connection through an HTTPS proxy using HTTPS CONNECT." << std::endl;
+ std::cerr << "stdin is sent to the tunneled connection, output is sent to stdout." << std::endl;
+ std::cerr << "Intended for use as an SSH ProxyCommand." << std::endl;
+}
+
+int main(int argc, char **argv)
+{
+ _setmode(_fileno(stdout), _O_BINARY);
+ _setmode(_fileno(stdin), _O_BINARY);
+
+ std::optional params;
+
+ try
+ {
+ params.emplace(argc, argv);
+ }
+ catch(const std::exception &ex)
+ {
+ std::cerr << ex.what() << std::endl;
+ std::cerr << std::endl;
+ const char *name = (argc > 0 && argv[0]) ? argv[0] : "win-httpstunnel.exe";
+ printUsage(name);
+ return -1;
+ }
+
+ try
+ {
+ SECURITY_STATUS err;
+
+ SecurityInterface secItf{};
+
+ Winsock ws{2, 2};
+ if(!ws.supportsVersion(2, 2))
+ throw std::runtime_error{"Winsock 2.2 is required"};
+
+ SspiCredHandle clientCred;
+ createClientCredential(secItf, clientCred);
+
+ // Resolve the proxy hostname
+ ADDRINFOA addrInfoHints{};
+ addrInfoHints.ai_family = AF_INET;
+ addrInfoHints.ai_socktype = SOCK_STREAM;
+ addrInfoHints.ai_protocol = IPPROTO_TCP;
+ ADDRINFOA *pProxyAddrInfoRaw{};
+ err = ::getaddrinfo(params->proxyHost(), "1", &addrInfoHints,
+ &pProxyAddrInfoRaw);
+ // Own the returned pointer
+ std::unique_ptr pProxyAddrInfo{pProxyAddrInfoRaw, &::freeaddrinfo};
+ if(err || !pProxyAddrInfo)
+ throw WinError{"Unable to resolve proxy hostname", err};
+ // Although getaddrinfo() returns a linked list of addresses, we asked
+ // for IPv4 only, so we just inspect the first one.
+ if(pProxyAddrInfo->ai_family != AF_INET ||
+ pProxyAddrInfo->ai_addrlen != sizeof(SOCKADDR_IN) || !pProxyAddrInfo->ai_addr)
+ throw std::runtime_error{"Proxy host was resolved but did not return an IPv4 address"};
+ const SOCKADDR_IN *pProxyAddr = reinterpret_cast(pProxyAddrInfo->ai_addr);
+
+ WinSocket socket{AF_INET, SOCK_STREAM, IPPROTO_TCP};
+ SOCKADDR_IN sin{};
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(params->proxyPort());
+ sin.sin_addr.S_un.S_addr = pProxyAddr->sin_addr.S_un.S_addr;
+
+ if(socket.connect(reinterpret_cast(&sin), sizeof(sin)))
+ {
+ throw WinError{"Unable to connect to remote host", ::WSAGetLastError()};
+ }
+
+ SspiCtxtHandle secureCtxt{secItf};
+ std::vector receivedData;
+ secureHandshake(secItf, clientCred, socket, params->proxyHost(), secureCtxt, receivedData);
+
+ SecPkgContext_StreamSizes sizes{};
+ err = secItf.get().QueryContextAttributes(secureCtxt.get(), SECPKG_ATTR_STREAM_SIZES, &sizes);
+ if(err != SEC_E_OK)
+ throw WinError{"Failed to query message size limits", err};
+
+ MsgBuf sendBuf{sizes};
+ std::size_t httpsConnectMsgSize{0};
+ appendMsg(sendBuf, httpsConnectMsgSize, "CONNECT ");
+ appendMsg(sendBuf, httpsConnectMsgSize, params->tunnelTarget());
+ appendMsg(sendBuf, httpsConnectMsgSize, " HTTP/1.1");
+ appendMsg(sendBuf, httpsConnectMsgSize, "\r\nUser-Agent: win-httptunnel\r\nProxy-Authorization: Basic ");
+ appendMsg(sendBuf, httpsConnectMsgSize,
+ base64Encode(params->basicAuth(), std::strlen(params->basicAuth())));
+ appendMsg(sendBuf, httpsConnectMsgSize, "\r\n\r\n");
+ sendBuf.setMsgSize(httpsConnectMsgSize);
+
+ syncEncryptSend(secItf, socket, secureCtxt, sendBuf);
+ sendBuf.setMsgSize(sizes.cbMaximumMessage);
+
+ // At this point, since the TLS handshake is complete, receivedData is
+ // now the queue for encrypted data, which might already contain data.
+ //
+ // decryptedData will be the queue for decrypted received data, which
+ // may contain partial HTTP lines until we complete the CONNECT.
+ std::vector decryptedData;
+ std::string responseEnd{"\r\n\r\n"};
+ std::vector::iterator responseEndPos;
+
+ // Receive the HTTP CONNECT response.
+ while((responseEndPos = std::search(decryptedData.begin(), decryptedData.end(),
+ responseEnd.begin(), responseEnd.end())) == decryptedData.end())
+ {
+ char *pMsg{}, *pExtra{};
+ std::size_t msgLen{}, extraLen{};
+ syncReceiveDecrypt(secItf, socket, secureCtxt, receivedData, pMsg, msgLen, pExtra, extraLen);
+
+ // Add the decrypted "message" (which is a TLS message record, not
+ // necessarily a complete HTTP response) to the decrypted data
+ // queue
+ if(pMsg && msgLen > 0)
+ {
+ auto existingSize = decryptedData.size();
+ decryptedData.resize(existingSize + msgLen);
+ std::copy(pMsg, pMsg+msgLen, decryptedData.begin() + existingSize);
+ }
+
+ // Retain any extra data in the received data queue
+ if(pExtra && extraLen > 0)
+ {
+ receivedData.erase(receivedData.begin(), receivedData.begin() + (pExtra - receivedData.data()));
+ receivedData.resize(extraLen);
+ }
+ else
+ {
+ receivedData.resize(0);
+ }
+ }
+
+ // Make sure we got 200 OK
+ const char *pResponseEnd = decryptedData.data();
+ pResponseEnd += (responseEndPos - decryptedData.begin());
+ readHttpsConnectResponse(decryptedData.data(), pResponseEnd);
+
+ // If we got any extra decrypted data, write it out now.
+ responseEndPos += responseEnd.size();
+ pResponseEnd += responseEnd.size(); // Valid because we matched this string
+ std::cout.write(pResponseEnd, decryptedData.end() - responseEndPos);
+ std::cout.flush();
+
+ // Poll both stdin and the socket's read/close events. Set up an event
+ // to use WaitForMultipleObjects().
+ WinSocketEvent socketEvent;
+ if(socket.eventSelect(socketEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR)
+ throw WinError{"Unable to select read/close events on socket", ::WSAGetLastError()};
+
+ HANDLE waitHandles[2]{socketEvent.get(), ::GetStdHandle(STD_INPUT_HANDLE)};
+
+ // Windows pipes are not waitable objects (:facepalm:) If stdin is a
+ // pipe, we have to fall back to short-polling.
+ DWORD waitHandleCount = 2;
+ DWORD waitTimeout = INFINITE;
+ if(GetFileType(waitHandles[1]) == FILE_TYPE_PIPE)
+ {
+ waitHandleCount = 1; // Don't wait on the pipe
+ waitTimeout = 100; // Wake periodically to try reading from the pipe
+ }
+
+ bool continueReading{true};
+ do
+ {
+ switch(::WaitForMultipleObjects(waitHandleCount, waitHandles, FALSE, waitTimeout))
+ {
+ case WAIT_OBJECT_0: // Socket
+ {
+ WSANETWORKEVENTS netEvents{};
+ if(socket.enumNetworkEvents(socketEvent, &netEvents) == SOCKET_ERROR)
+ throw WinError{"Failed to get network events from socket", ::WSAGetLastError()};
+
+ if(netEvents.lNetworkEvents & FD_READ)
+ {
+ // Read and forward to stdout
+ char *pMsg{}, *pExtra{};
+ std::size_t msgLen{}, extraLen{};
+ do
+ {
+ syncReceiveDecrypt(secItf, socket, secureCtxt, receivedData, pMsg, msgLen, pExtra, extraLen);
+ if(pMsg && msgLen > 0)
+ {
+ std::cout.write(pMsg, msgLen);
+ std::cout.flush();
+ }
+
+ if(pExtra && extraLen > 0)
+ {
+ receivedData.erase(receivedData.begin(), receivedData.begin() + (pExtra - receivedData.data()));
+ receivedData.resize(extraLen);
+ }
+ else
+ {
+ receivedData.resize(0);
+ }
+ }
+ // If we read a message and still have extra data, try
+ // to decrypt again, we might already have another
+ // message.
+ while(pMsg && msgLen > 0 && !receivedData.empty());
+ }
+ if(netEvents.lNetworkEvents & FD_CLOSE)
+ {
+ continueReading = false;
+ }
+ break;
+ }
+ case WAIT_OBJECT_0 + 1: // stdin
+ {
+ DWORD readSize{};
+ if(!::ReadFile(waitHandles[1], sendBuf.msgBuf(),
+ sendBuf.msgSize(), &readSize, nullptr))
+ {
+ throw WinError{"Failed to read from stdin", ::GetLastError()};
+ }
+ sendBuf.setMsgSize(readSize);
+ syncEncryptSend(secItf, socket, secureCtxt, sendBuf);
+ sendBuf.setMsgSize(sizes.cbMaximumMessage);
+ break;
+ }
+ case WAIT_TIMEOUT: // peek stdin pipe
+ {
+ DWORD readSize{};
+ do
+ {
+ if(!PeekNamedPipe(waitHandles[1], nullptr, 0, nullptr,
+ &readSize, nullptr))
+ {
+ throw WinError{"Failed to check for input on stdin", ::GetLastError()};
+ }
+ // If there is something to read, read up to a message
+ // length (then check again).
+ if(readSize)
+ {
+ if(!ReadFile(waitHandles[1], sendBuf.msgBuf(),
+ sendBuf.msgSize(), &readSize, nullptr))
+ {
+ throw WinError{"Failed to read from stdin", ::GetLastError()};
+ }
+ sendBuf.setMsgSize(readSize);
+ syncEncryptSend(secItf, socket, secureCtxt, sendBuf);
+ sendBuf.setMsgSize(sizes.cbMaximumMessage);
+ }
+ }
+ while(readSize > 0);
+ break;
+ }
+ default:
+ // Any other result is unexpected. (WAIT_FAILED is
+ // obviously an error, we don't expect any abandon results
+ // since we are not waiting on mutexes.)
+ throw std::runtime_error{"Failed waiting on input events"};
+ }
+ }
+ while(continueReading);
+ }
+ catch(const WinError &ex)
+ {
+ std::cerr << ex.what() << std::endl;
+ std::cerr << "(" << ex.getWinErr() << ") " << ex.getWinMsg() << std::endl;
+ return -1;
+ }
+ catch(const std::exception &ex)
+ {
+ std::cerr << ex.what() << std::endl;
+ return -1;
+ }
+}