#
# shater-core — data-plane glue for the Shater transparent-proxy stack (v0.2).
#
# Ships the "железно" (rock-solid) static layer that the single Go binary
# `shaterd` sits under: the procd init that supervises `shaterd run` (which
# embeds the sing-box engine + control-plane + DNS in-process), the auto-update
# cron loop, the hotplug hook that re-persists policy routing, the sysctl knobs
# TPROXY needs, one-time rt_tables seeding, and a minimal inert UCI default.
#
# Pure scripts + config => PKGARCH:=all. Nothing is compiled here.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=shater-core

# Version comes from the git tag via ci/version.sh -> SHATER_PKG_VERSION /
# SHATER_PKG_RELEASE in the SDK build env (see openwrt/shaterd/Makefile for the
# full rationale — bug B4: v0.2.2…v0.2.6 all shipped as 0.2.0-r3). The literals
# are the manual/offline fallback only.
PKG_VERSION:=$(if $(SHATER_PKG_VERSION),$(SHATER_PKG_VERSION),0.2.0)
PKG_RELEASE:=$(if $(SHATER_PKG_RELEASE),$(SHATER_PKG_RELEASE),1)

PKG_MAINTAINER:=Shater <maqrota@icloud.com>
PKG_LICENSE:=GPL-2.0-or-later

include $(INCLUDE_DIR)/package.mk

define Package/shater-core
  SECTION:=net
  CATEGORY:=Network
  TITLE:=Shater transparent-proxy data-plane glue
  URL:=https://github.com/shater
  # v0.2 collapses the old xrayctl + xray-core + dnsmasq-full trio into ONE Go
  # binary, shaterd, which embeds the sing-box engine, the control-plane AND an
  # in-process DNS server. So we no longer depend on:
  #   - xrayctl / xray-core  -> replaced by shaterd
  #   - dnsmasq-full         -> the engine owns the :53 hijack listener now
  # We still need the kernel TPROXY modules and ip-full for policy routing:
  #   shaterd              : the daemon our init supervises (`shaterd run`)
  #   kmod-nft-tproxy      : kernel TPROXY (shaterd emits the `inet shater` rules)
  #   kmod-nft-socket      : socket match used by the tproxy divert chain
  #   kmod-tun             : /dev/net/tun — the daemon opens the `shater-l3` TUN
  #                          for L3 ingress (globals.l3_tunnel); usually built-in
  #                          on stock images, but a slimmed image without it would
  #                          make the option fail with a cryptic open() error.
  #   ip-full              : `ip rule`/`ip route`/rt_tables for policy routing
  #   nftables-json        : shaterd shells out to `nft`, and netplane/stats.go
  #                          parses `nft -j list ...` — the JSON output only exists
  #                          in the json variant (the -nft variant has no libjansson).
  #                          fw4 already pulls it on stock images; declare it so a
  #                          slimmed image cannot silently break counters/sets.
  #   ca-bundle            : the daemon is CGO_ENABLED=0, so crypto/x509 has no
  #                          host cert fallback — without /etc/ssl/certs every
  #                          HTTPS subscription / .srs ruleset fetch fails.
  DEPENDS:=+shaterd +kmod-nft-tproxy +kmod-nft-socket +kmod-tun +ip-full +nftables-json +ca-bundle
  PKGARCH:=all
endef

define Package/shater-core/description
  Static data-plane glue for the Shater sing-box-based transparent proxy: procd
  init (supervises `shaterd run`, which owns the engine + nft table `inet shater`
  + policy routing + in-process DNS), an auto-update cron loop with a dead-engine
  watchdog, an ifup/ifdown hotplug hook that re-persists ip rules & routes,
  TPROXY sysctl settings, a minimal inert UCI default (globals disabled until
  configured), and idempotent first-boot setup. Designed to never break
  connectivity: fully inert until explicitly enabled.
endef

# /etc/config/shater is user-editable desired state -> preserve on upgrade.
define Package/shater-core/conffiles
/etc/config/shater
endef

# Nothing to fetch or build.
define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
endef

define Build/Compile
endef

define Package/shater-core/install
	$(INSTALL_DIR) $(1)/etc/init.d
	$(INSTALL_BIN) ./files/etc/init.d/shater $(1)/etc/init.d/shater
	$(INSTALL_BIN) ./files/etc/init.d/shater-cron $(1)/etc/init.d/shater-cron
	# START=21 one-shot that loads the persisted fail-closed plane before fw4's
	# `lan -> wan ACCEPT` can be the only thing on the box (the main init is
	# START=99, i.e. seconds of plaintext forwarding on every boot).
	$(INSTALL_BIN) ./files/etc/init.d/shater-armor $(1)/etc/init.d/shater-armor

	$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
	$(INSTALL_BIN) ./files/etc/hotplug.d/iface/99-shater $(1)/etc/hotplug.d/iface/99-shater

	$(INSTALL_DIR) $(1)/etc/sysctl.d
	$(INSTALL_DATA) ./files/etc/sysctl.d/99-shater.conf $(1)/etc/sysctl.d/99-shater.conf

	$(INSTALL_DIR) $(1)/etc/config
	$(INSTALL_CONF) ./files/etc/config/shater $(1)/etc/config/shater

	# THE SAME FILE AGAIN, READ-ONLY, AS DOCUMENTATION. /etc/config/shater is 271
	# lines of which 248 are comment, and on the router it is the only description
	# of the schema there is (PORTING.md does not ship). Being a conffile keeps an
	# upgrade from replacing it, but it does NOT keep the daemon from rewriting it:
	# the config write path replaces the whole package (`uci delete shater` + `uci
	# import`), which drops every comment — and it runs without an operator, from
	# the panel, the 6-hourly subscription refresh and the 25-second profile
	# watcher. So the annotated original is installed a second time where nothing
	# rewrites it, and the header of the live file points at it.
	#
	# INSTALL_DATA, not INSTALL_CONF: this copy is package metadata (refreshed by
	# every upgrade so it documents the build actually installed), not user config.
	$(INSTALL_DIR) $(1)/usr/share/shater
	$(INSTALL_DATA) ./files/etc/config/shater $(1)/usr/share/shater/config.sample

	$(INSTALL_DIR) $(1)/etc/uci-defaults
	$(INSTALL_BIN) ./files/etc/uci-defaults/30_shater-core $(1)/etc/uci-defaults/30_shater-core

	# sysupgrade's "keep settings" walks /lib/upgrade/keep.d/*, and without this the
	# node inventory in /etc/shater/subs does NOT survive a flash: the restored box
	# has its rules and its groups and no nodes for them to point at, and the only
	# repair is `sub update`, which needs the internet the tunnel was going to
	# provide. Package metadata, not user config, so INSTALL_DATA and not
	# INSTALL_CONF. (/etc/config/shater needs no entry — it is a conffile and
	# sysupgrade already keeps it that way.)
	$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
	$(INSTALL_DATA) ./files/lib/upgrade/keep.d/shater-core $(1)/lib/upgrade/keep.d/shater-core
endef

$(eval $(call BuildPackage,shater-core))
