#!/bin/sh /etc/rc.common

USE_PROCD=1
# after network
START=21

my_extra_command() {
	local cmd="$1"
	local help="$2"

	local extra="$(printf "%-16s%s" "${cmd}" "${help}")"
	EXTRA_HELP="${EXTRA_HELP}	${extra}
"
	EXTRA_COMMANDS="${EXTRA_COMMANDS} ${cmd}"
}
my_extra_command stop_fw "Stop zapret firewall (noop in iptables+fw3 case)"
my_extra_command start_fw "Start zapret firewall (noop in iptables+fw3 case)"
my_extra_command restart_fw "Restart zapret firewall (noop in iptables+fw3 case)"
my_extra_command reload_ifsets "Reload interface lists (nftables only)"
my_extra_command list_ifsets "Display interface lists (nftables only)"
my_extra_command list_table "Display zapret nftable (nftables only)"
my_extra_command stop_daemons "Stop zapret daemons only (=stop in iptables+fw3 case)"
my_extra_command start_daemons "Start zapret daemons only (=start in iptables+fw3 case)"
my_extra_command restart_daemons "Restart zapret firewall only (=restart in iptables+fw3 case)"

SCRIPT=$(readlink /etc/init.d/zapret)
if [ -n "$SCRIPT" ]; then
 EXEDIR=$(dirname "$SCRIPT")
 ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
else
 ZAPRET_BASE=/opt/zapret
fi

. "$ZAPRET_BASE/init.d/openwrt/functions"


# !!!!! in old openwrt 21.x- with iptables firewall rules are configured separately
# !!!!! in new openwrt >21.x with nftables firewall is configured here

PIDDIR=/var/run

[ -n "$NFQWS" ] || NFQWS="$ZAPRET_BASE/nfq/nfqws"
NFQWS_OPT_BASE="--user=$WS_USER --dpi-desync-fwmark=$DESYNC_MARK"

[ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws"
TPWS_OPT_BASE="--user=$WS_USER"
TPWS_OPT_BASE4="--bind-addr=$TPWS_LOCALHOST4"
TPWS_OPT_BASE6="--bind-addr=::1"
TPWS_WAIT="--bind-wait-ifup=30 --bind-wait-ip=30"
TPWS_WAIT_SOCKS6="$TPWS_WAIT --bind-wait-ip-linklocal=30"
TPWS_OPT_BASE6_PRE="--bind-linklocal=prefer $TPWS_WAIT --bind-wait-ip-linklocal=3"

run_daemon()
{
	# $1 - daemon string id or number. can use 1,2,3,...
	# $2 - daemon
	# $3 - daemon args
	# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
	local DAEMONBASE="$(basename "$2")"
	echo "Starting daemon $1: $2 $3"
	procd_open_instance
	procd_set_param command $2 $3
	procd_set_param pidfile $PIDDIR/$DAEMONBASE$1.pid
	procd_close_instance
}

run_tpws()
{
	[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && return 0

	local OPT="$TPWS_OPT_BASE"
	local DEVICE

	[ "$DISABLE_IPV4" = "1" ] || OPT="$OPT $TPWS_OPT_BASE4"
	[ "$DISABLE_IPV6" = "1" ] || {
		OPT="$OPT $TPWS_OPT_BASE6"
		for lan in $OPENWRT_LAN; do
		    network_get_device DEVICE $lan
		    [ -n "$DEVICE" ] && OPT="$OPT --bind-iface6=$DEVICE $TPWS_OPT_BASE6_PRE"
		done
	}
	run_daemon $1 "$TPWS" "$OPT $2"
}
run_tpws_socks()
{
	[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && return 0

	local opt="$TPWS_OPT_BASE --socks"

	tpws_apply_socks_binds opt
	run_daemon $1 "$TPWS" "$opt $2"
}

stop_tpws()
{
	stop_daemon $1 "$TPWS"
}


tpws_apply_socks_binds()
{
	local o

	[ "$DISABLE_IPV4" = "1" ] || o="--bind-addr=127.0.0.1"
	[ "$DISABLE_IPV6" = "1" ] || o="$o --bind-addr=::1"
	
	for lan in $OPENWRT_LAN; do
	    network_get_device DEVICE $lan
	    [ -n "$DEVICE" ] || continue
	    [ "$DISABLE_IPV4" = "1" ] || o="$o --bind-iface4=$DEVICE $TPWS_WAIT"
	    [ "$DISABLE_IPV6" = "1" ] || o="$o --bind-iface6=$DEVICE --bind-linklocal=unwanted $TPWS_WAIT_SOCKS6"
	done
	eval $1="\"\$$1 $o\""
}


start_daemons_procd()
{
	local opt qn qns qn6 qns6

	case "${MODE_OVERRIDE:-$MODE}" in
		tpws)
			opt="--port=$TPPORT $TPWS_OPT"
			filter_apply_hostlist_target opt
			filter_apply_suffix opt "$TPWS_OPT_SUFFIX"
			run_tpws 1 "$opt"
			;;
		tpws-socks)
			opt="--port=$TPPORT $TPWS_OPT"
			filter_apply_hostlist_target opt
			filter_apply_suffix opt "$TPWS_OPT_SUFFIX"
			run_tpws_socks 1 "$opt"
			;;
		nfqws)
			# quite complex but we need to minimize nfqws processes to save RAM
			get_nfqws_qnums qn qns qn6 qns6
			[ -z "$qn" ] || {
				opt="--qnum=$qn $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_HTTP"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_HTTP_SUFFIX"
				run_daemon 1 "$NFQWS" "$opt"
			}
			[ -z "$qns" ] || [ "$qns" = "$qn" ] || {
				opt="--qnum=$qns $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_HTTPS"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_HTTPS_SUFFIX"
				run_daemon 2 "$NFQWS" "$opt"
			}
			[ -z "$qn6" ] || [ "$qn6" = "$qn" ] || [ "$qn6" = "$qns" ] || {
				opt="--qnum=$qn6 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_HTTP6"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_HTTP6_SUFFIX"
				run_daemon 3 "$NFQWS" "$opt"
			}
			[ -z "$qns6" ] || [ "$qns6" = "$qn" ] || [ "$qns6" = "$qns" ] || [ "$qns6" = "$qn6" ] || {
				opt="--qnum=$qns6 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_HTTPS6"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_HTTPS6_SUFFIX"
				run_daemon 4 "$NFQWS" "$opt"
			}
			get_nfqws_qnums_quic qn qn6
			[ -z "$qn" ] || {
				opt="--qnum=$qn $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_QUIC"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_QUIC_SUFFIX"
				run_daemon 10 "$NFQWS" "$opt"
			}
			[ -z "$qn6" ] || [ "$qn6" = "$qn" ] || {
				opt="--qnum=$qn6 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_QUIC6"
				filter_apply_hostlist_target opt
				filter_apply_suffix opt "$NFQWS_OPT_DESYNC_QUIC6_SUFFIX"
				run_daemon 11 "$NFQWS" "$opt"
			}
			;;
		custom)
	    		custom_runner zapret_custom_daemons $1
			;;
	esac

	return 0
}
start_daemons()
{
	rc_procd start_daemons_procd "$@"
}
stop_daemons()
{
	local svc="$(basename ${basescript:-$initscript})"
	procd_running "$svc" "$1" && procd_kill "$svc" "$1"
}
restart_daemons()
{
	stop_daemons
	start_daemons
}

start_fw()
{
	zapret_apply_firewall
}
stop_fw()
{
	zapret_unapply_firewall
}
restart_fw()
{
	stop_fw
	start_fw
}
reload_ifsets()
{
	zapret_reload_ifsets
}
list_ifsets()
{
	zapret_list_ifsets
}
list_table()
{
	zapret_list_table
}

start_service()
{
	start_daemons_procd
	[ "$INIT_APPLY_FW" != "1" ] || {
		linux_fwtype
		openwrt_fw3_integration || start_fw
	}
}

stop_service()
{
	# this procedure is called from stop()
	# stop() already stop daemons
	[ "$INIT_APPLY_FW" != "1" ] || {
		linux_fwtype
		openwrt_fw3_integration || stop_fw
	}
}
