vpn eww and eww crash
This commit is contained in:
@@ -34,3 +34,10 @@
|
||||
.bt-device-btn:hover { @include background-active; }
|
||||
.net-toggle-on, .bt-btn-on { @include color-base; }
|
||||
.net-toggle-off, .bt-btn-off { @include color-inactive; }
|
||||
|
||||
// WireGuard
|
||||
.wg-accent { background-color: $base0E; }
|
||||
.wg-row { margin-bottom: $popup-scale * 4pt; }
|
||||
.wg-name { font-size: 0.78em; font-weight: bold; }
|
||||
.wg-up { @include color-base; }
|
||||
.wg-down { @include color-inactive; }
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
(defwidget clock-mod []
|
||||
(module
|
||||
(eventbox
|
||||
:onhover "${EWW_CMD} update date_rev=true"
|
||||
:onhoverlost "${EWW_CMD} update date_rev=false"
|
||||
:onhover "${EWW_CMD} --no-daemonize update date_rev=true"
|
||||
:onhoverlost "${EWW_CMD} --no-daemonize update date_rev=false"
|
||||
:onclick "scripts/panel-toggle clock"
|
||||
:onrightclick "scripts/powermenu-toggle"
|
||||
(box
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(deflisten net
|
||||
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""}}'
|
||||
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""},"wireguard":[],"vpn":{"up":false,"name":""}}'
|
||||
"scripts/net/net")
|
||||
|
||||
(deflisten bt
|
||||
@@ -20,6 +20,11 @@
|
||||
:class "net-icon net-active"
|
||||
:tooltip "USB: Connected"
|
||||
:text "")
|
||||
(label
|
||||
:visible {net.vpn.up}
|
||||
:class "net-icon net-active"
|
||||
:tooltip "VPN: ${net.vpn.name}"
|
||||
:text "")
|
||||
(label
|
||||
:class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}"
|
||||
:tooltip {net.wifi.connected ? "WiFi: ${net.wifi.ssid}" : "WiFi: Disconnected"}
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
# top of every wrapped script, right after setting PATH.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Every eww client call goes through this wrapper. A client waits only 100 ms
|
||||
# for the daemon's reply; a slower command (opening the popup) would otherwise
|
||||
# make a plain `eww open` fork a second daemon that takes over the socket —
|
||||
# the "two bars" bug. With --no-daemonize it is just an error, and the daemon
|
||||
# still carries out the command.
|
||||
eww() { command eww --no-daemonize "$@"; }
|
||||
|
||||
# Print the payload only when it differs from the previous one.
|
||||
emit() {
|
||||
[[ $1 == "${EMIT_LAST-}" ]] && return 0
|
||||
|
||||
@@ -70,8 +70,60 @@ state() {
|
||||
"$w_connected" "$w_enabled" "$w_icon" "$(jstr "$w_ssid")" "$w_ip" "${w_freq:-0}" "$(band "$w_freq")" "$w_gen" "${w_signal:-0}"
|
||||
printf '"ethernet":{"connected":%s,"interface":"%s","ip":"%s","speed":"%s"},' \
|
||||
"$e_connected" "$eth" "$e_ip" "$e_speed"
|
||||
printf '"usb":{"connected":%s,"interface":"%s","ip":"%s"}}' \
|
||||
printf '"usb":{"connected":%s,"interface":"%s","ip":"%s"},' \
|
||||
"$u_connected" "$usb" "$u_ip"
|
||||
wg_json
|
||||
printf '}'
|
||||
}
|
||||
|
||||
# --- WireGuard: interfaces from the wireguard-<name>.service units (so a
|
||||
# tunnel that is down still shows up) plus any live wireguard-type link.
|
||||
# `wg show` needs root, so peer names and the endpoint come from the peer
|
||||
# units instead.
|
||||
|
||||
wg_ifaces() {
|
||||
{
|
||||
systemctl list-units --all --plain --no-legend 'wireguard-*.service' 2>/dev/null \
|
||||
| awk '$1 !~ /-peer-/ { sub(/^wireguard-/, "", $1); sub(/\.service$/, "", $1); print $1 }'
|
||||
ip -d -o link 2>/dev/null | awk '/ wireguard / { sub(":", "", $2); print $2 }'
|
||||
} | sort -u
|
||||
}
|
||||
|
||||
human_bytes() {
|
||||
awk -v b="${1:-0}" 'BEGIN {
|
||||
split("B KiB MiB GiB TiB", u, " "); i = 1
|
||||
while (b >= 1024 && i < 5) { b /= 1024; i++ }
|
||||
printf (i == 1 ? "%d %s" : "%.1f %s"), b, u[i] }'
|
||||
}
|
||||
|
||||
wg_json() { # prints the "wireguard" array and the "vpn" summary
|
||||
local name up ip rx tx peers endpoint peer_unit peer_script sep="" out="[" vpn_up=false vpn_name=""
|
||||
while read -r name; do
|
||||
[[ -n $name ]] || continue
|
||||
up=false ip="" rx=0 tx=0 endpoint=""
|
||||
if [[ -d /sys/class/net/$name ]]; then
|
||||
ip -o link show "$name" 2>/dev/null | grep -q '<[^>]*UP' && up=true
|
||||
ip=$(ipv4 "$name")
|
||||
rx=$(<"/sys/class/net/$name/statistics/rx_bytes")
|
||||
tx=$(<"/sys/class/net/$name/statistics/tx_bytes")
|
||||
fi
|
||||
peers=$(systemctl list-units --all --plain --no-legend "wireguard-$name-peer-*.service" 2>/dev/null \
|
||||
| awk '{ print $1 }' | sed "s/^wireguard-$name-peer-//; s/\.service\$//" | paste -sd, -)
|
||||
peer_unit=$(systemctl list-units --all --plain --no-legend "wireguard-$name-peer-*.service" 2>/dev/null \
|
||||
| awk 'NR == 1 { print $1 }')
|
||||
# NixOS puts `wg set … endpoint "host:port"` in the peer unit's start script
|
||||
if [[ -n $peer_unit ]]; then
|
||||
peer_script=$(systemctl show -p ExecStart --value "$peer_unit" 2>/dev/null \
|
||||
| sed -n 's/.*path=\([^ ;]*\).*/\1/p' | awk 'NR == 1')
|
||||
[[ -r $peer_script ]] && endpoint=$(grep -o 'endpoint "[^"]*"' "$peer_script" 2>/dev/null \
|
||||
| awk -F'"' 'NR == 1 { print $2 }')
|
||||
fi
|
||||
if [[ $up == true && $vpn_up == false ]]; then vpn_up=true vpn_name=$name; fi
|
||||
[[ -z $vpn_name ]] && vpn_name=$name
|
||||
out+="$sep{\"name\":\"$(jstr "$name")\",\"up\":$up,\"ip\":\"$ip\",\"rx\":\"$(human_bytes "$rx")\",\"tx\":\"$(human_bytes "$tx")\",\"peers\":\"$(jstr "$peers")\",\"endpoint\":\"$(jstr "$endpoint")\"}"
|
||||
sep=,
|
||||
done < <(wg_ifaces)
|
||||
printf '"wireguard":%s],"vpn":{"up":%s,"name":"%s"}' "$out" "$vpn_up" "$(jstr "$vpn_name")"
|
||||
}
|
||||
|
||||
refresh() { emit "$(state)"; }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring the WireGuard tunnel $1 down (stop its service, which takes the peer
|
||||
# units with it) or up (start its target, which pulls service and peers).
|
||||
# Needs the polkit rule from modules/nixos/system/network/wireguard.
|
||||
name=$1
|
||||
[[ -n $name ]] || exit 64
|
||||
if [[ -d /sys/class/net/$name ]]; then
|
||||
systemctl stop "wireguard-$name.service"
|
||||
else
|
||||
systemctl start "wireguard-$name.target"
|
||||
fi
|
||||
@@ -4,6 +4,11 @@
|
||||
# The popup hosts every panel behind revealers, so switching panels while it
|
||||
# is open is just a variable update (animated, no scripts restarted). It is
|
||||
# only closed and re-opened when it has to move to another monitor.
|
||||
#
|
||||
# `eww open popup` takes longer than the client's 100 ms reply deadline, so
|
||||
# its exit status and error output are meaningless and ignored (the daemon
|
||||
# carries the command out anyway; the lib's eww wrapper makes sure a slow
|
||||
# reply can never spawn a second daemon).
|
||||
panel=$1
|
||||
[[ -n $panel ]] || exit 64
|
||||
|
||||
@@ -12,7 +17,7 @@ panel=$1
|
||||
exec 9>"${XDG_RUNTIME_DIR:-/tmp}/eww-panel-toggle.lock"
|
||||
flock -n 9 || exit 0
|
||||
|
||||
ew() { timeout 5 eww "$@" 9>&-; }
|
||||
ew() { eww "$@" 9>&-; }
|
||||
|
||||
current=$(ew get active-panel 2>/dev/null | tr -d '"')
|
||||
popup_screen=$(ew get popup-screen 2>/dev/null | tr -d '"')
|
||||
@@ -21,15 +26,16 @@ if ew active-windows 2>/dev/null | grep -qx 'popup: popup'; then open=1; else op
|
||||
|
||||
if ((open)) && [[ $current == "$panel" ]]; then
|
||||
ew update active-panel=
|
||||
ew close popup
|
||||
ew close popup 2>/dev/null
|
||||
elif ((open)) && [[ -n $screen && $popup_screen == "$screen" ]]; then
|
||||
ew update active-panel="$panel"
|
||||
else
|
||||
((open)) && ew close popup
|
||||
((open)) && ew close popup 2>/dev/null
|
||||
ew update active-panel="$panel" popup-screen="$screen"
|
||||
if [[ -n $screen ]]; then
|
||||
ew open popup --screen "$screen"
|
||||
ew open popup --screen "$screen" >/dev/null 2>&1
|
||||
else
|
||||
ew open popup
|
||||
ew open popup >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# Toggle the full-screen power menu on the focused monitor.
|
||||
ew() { timeout 5 eww "$@"; }
|
||||
ew close popup 2>/dev/null
|
||||
ew update active-panel=
|
||||
# Toggle the full-screen power menu on the focused monitor. The open's exit
|
||||
# status is ignored: it exceeds the client's 100 ms reply deadline.
|
||||
eww close popup 2>/dev/null
|
||||
eww update active-panel= 2>/dev/null
|
||||
screen=$(eww-bar focused)
|
||||
if [[ -n $screen ]]; then
|
||||
ew open powermenu --toggle --screen "$screen"
|
||||
eww open powermenu --toggle --screen "$screen" >/dev/null 2>&1
|
||||
else
|
||||
ew open powermenu --toggle
|
||||
eww open powermenu --toggle >/dev/null 2>&1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -83,6 +83,29 @@
|
||||
:visible {!bt.powered}
|
||||
:text "Disabled")))
|
||||
|
||||
; --- WireGuard ---
|
||||
|
||||
(defwidget wg-row [wg]
|
||||
(box :orientation "v" :space-evenly false :class "wg-row"
|
||||
(box :orientation "h" :space-evenly false :valign "center"
|
||||
(label :class "wg-name ${wg.up ? 'wg-up' : 'wg-down'}" :halign "start" :hexpand true :text {wg.name})
|
||||
(button
|
||||
:class "net-toggle-btn ${wg.up ? 'net-toggle-on' : 'net-toggle-off'}"
|
||||
:onclick "scripts/net/wg-toggle ${wg.name}"
|
||||
:tooltip {wg.up ? "Disconnect" : "Connect"}
|
||||
(label :text {wg.up ? "" : ""})))
|
||||
(box :orientation "v" :space-evenly false :visible {wg.up}
|
||||
(netinfo-row :label "IP" :value {wg.ip})
|
||||
(netinfo-row :label "Peer" :value {wg.endpoint != "" ? "${wg.peers} · ${wg.endpoint}" : wg.peers})
|
||||
(netinfo-row :label "Traffic" :value " ${wg.rx} ${wg.tx}"))
|
||||
(label :class "netinfo-dim" :halign "start" :visible {!wg.up} :text "Down")))
|
||||
|
||||
(defwidget wireguard-net-section []
|
||||
(box :orientation "v" :space-evenly false :class "sys-section"
|
||||
(section-header :title "WireGuard" :accent "wg-accent")
|
||||
(for wg in {net.wireguard}
|
||||
(wg-row :wg {wg}))))
|
||||
|
||||
; --- Root ---
|
||||
|
||||
(defwidget net-win []
|
||||
@@ -94,4 +117,7 @@
|
||||
(box :class "section-sep")
|
||||
(wifi-net-section)
|
||||
(box :class "section-sep")
|
||||
(box :visible {arraylength(net.wireguard) > 0} :space-evenly false :orientation "v"
|
||||
(wireguard-net-section)
|
||||
(box :class "section-sep"))
|
||||
(bluetooth-net-section)))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
(pm-btn :icon "" :label "Sign out"
|
||||
:onclick "hyprctl eval \"hl.dispatch(hl.dsp.exit())\"")
|
||||
(pm-btn :icon "" :label "Cancel"
|
||||
:onclick "eww close powermenu")))))))
|
||||
:onclick "${EWW_CMD} --no-daemonize close powermenu")))))))
|
||||
|
||||
(defwindow powermenu
|
||||
:monitor 0
|
||||
|
||||
@@ -20,6 +20,7 @@ let
|
||||
"scripts/net/net" = mkScript "net" ./bar/scripts/net/net [ iproute2 wpa_supplicant ];
|
||||
"scripts/net/bt" = mkScript "bt" ./bar/scripts/net/bt [ jq glib ];
|
||||
"scripts/net/bt-toggle" = mkScript "bt-toggle" ./bar/scripts/net/bt-toggle [ bluez ];
|
||||
"scripts/net/wg-toggle" = mkScript "wg-toggle" ./bar/scripts/net/wg-toggle [ ];
|
||||
"scripts/sys/gpu" = mkScript "gpu" ./bar/scripts/sys/gpu [ custom.amdgpu_top jq ];
|
||||
"scripts/sys/memory" = mkScript "memory" ./bar/scripts/sys/memory [ ];
|
||||
"scripts/sys/battery" = mkScript "battery" ./bar/scripts/sys/battery [ ];
|
||||
|
||||
@@ -36,6 +36,20 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# Let the desktop (eww network panel, scripts/net/wg-toggle) bring the
|
||||
# tunnel up and down. eww runs as a user service outside the login
|
||||
# session, where polkit cannot ask for a password, so wheel users may
|
||||
# start/stop wireguard-* units without one.
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
subject.isInGroup("wheel") &&
|
||||
/^wireguard-/.test(action.lookup("unit") || "")) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
systemd.services."wireguard-wg0-peer-vpn-helcel" = {
|
||||
after = [ "network-online.target" "nss-lookup.target" ];
|
||||
bindsTo = [ "network-online.target" ];
|
||||
|
||||
Reference in New Issue
Block a user