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

# shellcheck disable=SC2044
# shellcheck disable=SC2068

. $IPKG_INSTROOT/lib/functions/network.sh

# Comment out the START declaration to prevent the init file from
# actually starting tunneldigger at startup.  Instead rely on the
# hotplug scripts
#START=90

PIDPATH=/var/run
tunnel_id=0

tunnel_is_up() {
        local iface=$1
        local pidfile="${PIDPATH}/tunneldigger.${iface}.pid"
        local pid=0
        local result=0

        [ -e ${pidfile} ] && pid="$(cat ${pidfile})"
        [ ${pid} != 0 ] && [ -d "/proc/${pid}" ] && result=1
        echo "${result}"
}

interface_disabled() {
        local iface=$1
        local disabled
        disabled="$(uci -q get network.${iface}.disabled)"
        [ -z $disabled ] && disabled=0
        echo "${disabled}"
}
 
srv_lookup() {
        local srv="$1"
        local i
        local srvlist=""
        for i in $srv; do
                local lookup
                lookup="$(nslookup -q=SRV $i | grep $i | cut -d "=" -f 2)"
                local OLDIFS=$IFS
                IFS=$'\n'
                local j
                for j in $lookup; do
                        local host
                        local port
                        host="$(echo $j | cut -d ' ' -f 5)"
                        port="$(echo $j | cut -d ' ' -f 4)"
                        append srvlist "${host}:${port}"
                done
                IFS=$OLDIFS
        done

        echo "${srvlist}"
}

missing() {
        echo "Not starting tunneldigger \"$1\" - missing $2" >&2
}

handle_td() {
        local cfg="$1"; shift
        # determine if we should start only this instance
        local sections=("$@")
        local argn="$#"
        local skip=0
        if [ $argn -ne 0 ]; then
                skip=1
                for section in "${sections[@]}"; do
                        if [ "$cfg" == "$section" ]; then
                                skip=0
                                break
                        fi
                done
                if [ $skip -ne 0 ]; then
                        return
                fi
        fi

        local enabled
        local srv
        local addresses
        local uuid
        local interface
        local group
        local limit_bw_down
        local hook_script
        local broker_selection

        config_get_bool enabled "$cfg" enabled 1
        config_get srv "$cfg" srv
        config_get addresses "$cfg" address
        config_get uuid "$cfg" uuid
        config_get interface "$cfg" interface
        config_get group "$cfg" group
        config_get limit_bw_down "$cfg" limit_bw_down
        config_get hook_script "$cfg" hook_script
        config_get broker_selection "$cfg" broker_selection

        let tunnel_id++
			
        [ $enabled -eq 0 ] && return
        [ "$(interface_disabled ${interface})" == "1" ] && \
                echo "Not starting tunneldigger \"${cfg}\", interface ${interface} disabled" && return
        [ "$(tunnel_is_up ${interface})" == "1" ] && \
                echo "Not starting tunneldigger \"${cfg}\", already started" && return

        local broker_opts=""

        # use addresses provided by srv before the addresses list
        # in most circumstances, only an srv entry should be found
        # or a list of addresses.  Here, we handle both.
        srvlist=$(srv_lookup "$srv")
        local address
        local count=0
        for address in $srvlist $addresses; do
                count=$(($count+1))
                [ $count -gt 10 ] && break # limit of 10 addresses
                append broker_opts "-b ${address}"
        done

        [ ! -z "${limit_bw_down}" ] && append broker_opts "-L ${limit_bw_down}"
        [ ! -z "${hook_script}" ] && append broker_opts "-s ${hook_script}"
        [ ! -z "${broker_selection}" ] && {
                # Set broker selection.
                case "${broker_selection}" in
                        usage)
                                append broker_opts "-a"
                        ;;
                        first)
                                append broker_opts "-g"
                        ;;
                        random)
                                append broker_opts "-r"
                        ;;
                esac
        }

        if [ -z "$uuid" ]; then
                missing $cfg uuid
                return
        elif [ -z "$interface" ]; then
                missing $cfg interface
                return
        fi

        echo "Starting tunneldigger \"$cfg\" on ${interface}"
        /sbin/start-stop-daemon -S -q -b -m -c root:${group} -p ${PIDPATH}/tunneldigger.${interface}.pid -x /usr/bin/tunneldigger -- -u ${uuid} -i ${interface} -t ${tunnel_id} ${broker_opts}
}

# the start function can take arguements.  Without any arguements, the default behavior is
# to start all tunneldigger sections.  With arguements, only the listed tunneldigger
# sections are started
start() {
        config_load tunneldigger
        config_foreach handle_td broker $@
}

# the stop function can take arguements.  Without any arguements, the default behavior is
# to stop all tunneldigger sections.  With arguements, only the listed tunneldigger
# sections are stopped
stop() {
        local sections=("$@")
        local argn=$#
        for PIDFILE in `find ${PIDPATH}/ -name "tunneldigger\.*\.pid"`; do
                PID="$(cat ${PIDFILE})"
                IFACE="$(echo ${PIDFILE} | awk -F\/tunneldigger '{print $2}' | cut -d'.' -f2)"
                # determine if we should stop only this instance
                local skip=0
                if [ $argn -ne 0 ]; then
                        skip=1
                        for section in "${sections[@]}"; do
                                local section_iface
                                section_iface="$(uci get tunneldigger.${section}.interface)"
                                if [ $IFACE = $section_iface ]; then
                                        skip=0
                                        break
                                fi
                         done
                         if [ $skip -ne 0 ]; then
                                continue
                         fi
                fi
                echo "Stopping tunneldigger for interface ${IFACE}"
                start-stop-daemon -K -q -p $PIDFILE 
                while test -d "/proc/${PID}"; do
                        echo "  waiting for tunneldigger to stop"
                        sleep 1
                done
                rm -f ${PIDFILE}
                echo "  tunneldigger stopped"
        done
}

# the restart function can take arguements.  Without any arguements, the default behavior is
# to restart all tunneldigger sections.  With arguements, only the listed tunneldigger
# sections are restarted
restart() {
        stop $@
        start $@
}

