#!/bin/sh
# =====================================================================
# NetworkManager dispatcher —— 让热点跟随 Wi-Fi 客户端的信道
#
# 为什么需要它：
#   Intel CNVi 的接口组合是 #{ managed } <= 1, #{ AP } <= 1, total <= 3,
#   #channels <= 1 ——「客户端 + 热点」可以并存，但只能共占**一条**信道。
#   ap5g 的共存模式把热点放在虚拟接口上，一旦电脑换到一个不同信道的
#   Wi-Fi，这个组合就非法了：cfg80211 会直接以 -EBUSY 顶回连接请求，
#   用户看到的现象是「电脑连不上 Wi-Fi」，而不是明显的报错。
#
# 策略（只在 ap5g 开了共存模式时才动手）：
#   pre-up  无线客户端要激活 → 先把热点收掉，腾出信道让它连上（并记一个标记）
#   up/down 连接建立/断开     → 若之前热点是开着的，就按新信道重新拉起
#
# 其它情况一律直接退出：对没开共存模式的用户，这个钩子完全无感。
# 想彻底关掉：sudo ap5g set autofollow off（或删除本文件）。
# =====================================================================

IFACE="${1:-}"
ACTION="${2:-}"
[ -n "$IFACE" ] || exit 0

CONF=/etc/ap5g.conf
[ -r "$CONF" ] || exit 0

# 只认「单行 KEY=值」形式的配置（ap5g.conf 就是这种格式），
# 不去 source 它 —— dispatcher 以 root 跑，source 一个可写文件风险太大。
_conf_get() { sed -n "s/^$1=//p" "$CONF" 2>/dev/null | tail -1; }

APVIF="$(_conf_get AP_VIF)"
case "$APVIF" in "" | off | none | no | 0 | false | disabled) exit 0 ;; esac
case "$(_conf_get AUTO_FOLLOW)" in 0 | no | false | off) exit 0 ;; esac

# 只管物理无线网卡本身；我们自己的虚拟 AP 口（ap0）不在此列。
case "$IFACE" in "$APVIF") exit 0 ;; esac
[ -d "/sys/class/net/$IFACE/phy80211" ] || exit 0
[ -e "/sys/class/net/$IFACE/device" ] || exit 0

case "$ACTION" in pre-up | up | down | pre-down) ;; *) exit 0 ;; esac

AP5G=/usr/bin/ap5g
[ -x "$AP5G" ] || exit 0

LOG="logger -t ap5g-coexist"
RUN_DIR=/run
FLAG="$RUN_DIR/ap5g-coexist.was-on"
LOCK="$RUN_DIR/ap5g-coexist.lock"

# 串行化：NM 可能连续触发多个事件，重入会打架。
# flock 缺失时就退化成「不做互斥」，也比整个功能失效强。
if command -v flock >/dev/null 2>&1; then
    exec 9>"$LOCK" 2>/dev/null || { $LOG "无法创建锁文件，跳过"; exit 0; }
    flock -n 9 || exit 0
fi

ap_running() { [ -f "$RUN_DIR/ap-up.lastrun" ]; }

case "$ACTION" in
    pre-up)
        if ap_running; then
            : > "$FLAG"
            $LOG "Wi-Fi($IFACE) 即将连接：先停掉热点以腾出信道"
            "$AP5G" down >/dev/null 2>&1 || true
        fi
        ;;
    up | down)
        if [ -f "$FLAG" ]; then
            rm -f "$FLAG" 2>/dev/null || true
            $LOG "Wi-Fi($IFACE) 状态变化($ACTION)：按新信道重新拉起热点"
            # setsid 脱离会话，避免 NM/dispatcher 退出时把子进程带走；
            # 也绝不阻塞 NM 的状态机。
            setsid "$AP5G" up >/dev/null 2>&1 &
        fi
        ;;
esac

exit 0
