#!/bin/sh
#
# now only for inet state monitor and control led
#
MAIN_SLEEP_STEP=2
last_inet_state=255
boardModel=$(cat /etc/productInfo |grep 'boardModel=' |cut -d= -f2)
operator=$(cat /etc/productInfo |grep 'operator=' |cut -d= -f2)
workmode=$(uci -q get wanbackup.op.workmode)

#return 0, error
#return 1, OK
wan_is_connected() {
	local read status

	mesh_enable=$(uci -q get easyMesh.map.enable)
	mesh_role=$(uci -q get easyMesh.map.DeviceRole)

	# mesh enable controller or mesh disable and not repeater should check wan port is up
	# ignore slave connect to upstream router not by wan port case
	if [ "$mesh_enable" == "1" -a "$mesh_role" == "1" ] || [ "$mesh_enable" == "0" -a "$workmode" != "repeater" ] ; then
		read=$(switch reg r 0x7020 |awk -F 'value=' '{print $2}')
		status=$((0x$read & 1))
		if [ "$status" == "1" ]; then
			echo 1
		else
			echo 0
		fi
	else
		echo 1
	fi
}

#return 0, error
#return 1, OK
ping_check_baidu() {
	local wanconn result

	# if without -4 and ping www.baidu.com, will use IPv6 address of www.baidu.com
	result=`ping -4 -c 1 -W 1 baidu.com 2>/dev/null |grep avg`
	if [ -n "$result" ];then
		echo 1
	else
		echo 0
	fi
}

ping_check_qq() {
	local wanconn result

	result=`ping -4 -c 1 -W 1 qq.com 2>/dev/null |grep avg`
	if [ -n "$result" ];then
		echo 1
	else
		echo 0
	fi
}

ping_check_2235() {
	local wanconn result

	result=`ping -c 1 -W 1 223.5.5.5 2>/dev/null |grep avg`
	if [ -n "$result" ];then
		echo 1
	else
		echo 0
	fi
}

ping_check_8888() {
	local wanconn result

	result=`ping -c 1 -W 1 8.8.8.8 2>/dev/null |grep avg`
	if [ -n "$result" ];then
		echo 1
	else
		echo 0
	fi
}

# 0  disconnect internet
# 1  connect internet
# 2  wan is disconnect
ping_internet() {
	local ping_baidu ping_qq ping_2235 ping_8888
	local dns_2235_exist dns_exist

	ping_baidu=$(ping_check_baidu)
	if [ "$ping_baidu" == "1" ]; then
		echo 1
		return
	fi

	ping_qq=$(ping_check_qq)
	if [ "$ping_qq" == "1" ]; then
		echo 1
		return
	fi

	#ping_114=$(ping_check_114)
	ping_2235=$(ping_check_2235)
	ping_8888=$(ping_check_8888) # beacuse some province can't ping 114, e.x. JiangXi '
	if [ "$ping_2235" == "1" -o "$ping_8888" == "1" ]; then
		# force update nameserver:
		# ping domain name fail, but ip success
		dns_2235_exist=`cat /tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null |grep "223.5.5.5"`
		dns_exist=`cat /tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null |grep "nameserver"`
		if [ -z "$dns_exist" -a -z "$dns_2235_exist" ];then
			echo "nameserver 223.5.5.5" >> /tmp/resolv.conf.d/resolv.conf.auto

			gw_ip=`route -n  | grep UG | awk '{print $2}'`
			if [ "X$gw_ip" != "X" ];then
				echo "nameserver $gw_ip" >> /tmp/resolv.conf.d/resolv.conf.auto
			fi

			# force restart dnsmasq
			logger -t "[wan]" "force restart dnsmasq"
			/etc/init.d/dnsmasq restart
		fi

		echo 1
		return
	fi

	wanconn=$(wan_is_connected)
	if [ "$wanconn" != "1" ]; then
		logger -t "[wan]" "wan is not plug-in:`switch reg r 7020`"
		echo 2
		return
	else
		logger -t "[wan]" "ping internet fail."
		echo 0
        return
    fi
}

ping_gateway() {
	local result=0
	local ping_result
	local gateway=""

	dest=`route -n|head -3|tail -1 |awk '{print $1}'`
	if [ "$dest" == "0.0.0.0" ];then
		gateway=`route -n|head -3|tail -1|grep UG |awk '{print $2}'`
	fi
	if [ -n "$gateway" ];then
		ping_result=`ping $gateway -c 1 -W 3 2>/dev/null| grep avg 2>/dev/null`
		if [ -z "$ping_result" ];then
			ping_result=`ping $gateway -c 1 -W 1 2>/dev/null| grep avg 2>/dev/null`
			if [ -n "$ping_result" ];then
				result=1
			fi
		else
			result=1
		fi
	fi

	eval "$1=$result"
}

# check mesh
# in certain case, the agent maybe don't auto start mesh, '
# so try restart easymesh at system up.
mesh_poweron_check_done_file=/tmp/jcg_mesh_startup_check_flag
check_agent_mesh_at_system_up() {
	upTime=`cat /proc/uptime | cut -d' ' -f1 | cut -d'.' -f1`
	mesh_role=`jcg_mesh_helper.lua get_dev_role 2>/dev/null`
	bh_connection_status=`jcg_mesh_helper.lua get_bh_connection_status`

	# only work when mesh enable
	mesh_enable=`uci get easyMesh.map.enable`
	if [ "X$mesh_enable" != "X1" ]; then
		touch $mesh_poweron_check_done_file
		return
	fi

	# only for agent role
	if [ "X$mesh_role" == "X1" ]; then
		touch $mesh_poweron_check_done_file
		return
	fi

	# agent had connected, do nothing.
	if [ "X$bh_connection_status" == "X1" -a "X$mesh_role" == "X2" ];then
		echo "[mesh]Agent meshed OK at $upTime seconds!" > /dev/console
		touch $mesh_poweron_check_done_file
		return
	fi

	agent_detect_system_up_time=`uci get easyMesh.checker.agent_detect_system_up_time 2>/dev/null`
	if [ "X$agent_detect_system_up_time" == "X" ]; then
		agent_detect_system_up_time=110
	fi
	# if agent had been meshed, but don't auto start mesh after reboot, restart mesh '
	if [ $upTime -gt $agent_detect_system_up_time -a $upTime -lt 150 ];then
		BhProfile0Valid=`wificonf -f /etc/map/mapd_user.cfg get BhProfile0Valid 2>/dev/null`
		BhProfile1Valid=`wificonf -f /etc/map/mapd_user.cfg get BhProfile1Valid 2>/dev/null`

		if [ $BhProfile0Valid == 1 -o $BhProfile1Valid == 1 ]; then
			echo "[mesh]Agent exceed over $upTime seconds NOT meshed OK, restart mesh!" > /dev/console
			/sbin/wifi jcg_restart_mesh
		fi

		touch $mesh_poweron_check_done_file
	elif [ $upTime -gt 150 ];then
		echo "[mesh]Agent exceed over $upTime seconds NOT meshed OK, ignore it!" > /dev/console
		touch $mesh_poweron_check_done_file
	fi
}

# check mesh role
# when ethernet mesh, check real mesh role then update uci DeviceRole
is_check_mesh_role_done=0
last_mesh_role=99
check_mesh_role() {
	if [ "$is_check_mesh_role_done" == "1" ];then
		mesh_enable=`uci get easyMesh.map.enable`
		key_start_mesh=$(uci get easyMesh.map.key_start_mesh 2>/dev/null)
		uci_role=`uci -q get easyMesh.map.DeviceRole`
		if [ "X$mesh_enable" == "X1" -a "X$key_start_mesh" == "X1" -a "X$uci_role" == "X0" ]; then
			is_check_mesh_role_done=0
			last_mesh_role=99
		fi
		return
	fi

	# only work when mesh enable
	mesh_enable=`uci get easyMesh.map.enable`
	key_start_mesh=$(uci get easyMesh.map.key_start_mesh 2>/dev/null)
	if [ "X$mesh_enable" != "X1" -o "X$key_start_mesh" != "X1" ]; then # mesh disabled, do nonthing
		is_check_mesh_role_done=1
		return
	fi

	# initialize last mesh role
	if [ "$last_mesh_role" == "99" ]; then
		last_mesh_role=`jcg_mesh_helper.lua get_dev_role 2>/dev/null`
		if [ "X$last_mesh_role" != "X0" -a "X$last_mesh_role" != "X1" -a "X$last_mesh_role" != "X2" ]; then
		    last_mesh_role=99
		fi
	fi

	mesh_role=`jcg_mesh_helper.lua get_dev_role 2>/dev/null`
	uci_role=`uci -q get easyMesh.map.DeviceRole`
	agent_num=`jcg_mesh_helper.lua get_slave_num`
	if [ "X$mesh_role" == "X1" ]; then
		if [ "X$uci_role" == "X0" -a $agent_num -gt 0 ] || [ "$last_mesh_role" == "0" ]; then
			uci set easyMesh.map.DeviceRole=1;uci commit easyMesh
			wificonf -f /etc/map/mapd_user.cfg set DeviceRole 1
			wificonf -f /etc/dpp_cfg.txt set allowed_role 2

			is_check_mesh_role_done=1
		fi
	elif [ "X$mesh_role" == "X2" ]; then
		bh_status=`jcg_mesh_helper.lua get_bh_connection_status 2>/dev/null`
		if [ "X$uci_role" == "X0" -a "$bh_status" == "1" ]; then
			uci set easyMesh.map.DeviceRole=2;uci commit easyMesh
			wificonf -f /etc/map/mapd_user.cfg set DeviceRole 2

			is_check_mesh_role_done=1
		fi
	fi

    last_mesh_role=$mesh_role
}

#
# some boards have seperate mesh led
#
check_mesh_led() {
	local mesh_enable

	mesh_enable=`uci -q get easyMesh.map.enable`
	if [ "$boardModel" == "PK963M" -o "$boardModel" == "PK968M" ]; then
		if [ "X$mesh_enable" != "X1" ]; then
			/usr/bin/led_ctl mesh off
		fi
	elif [ "$boardModel" == "PK970M" ]; then
		/usr/bin/led_ctl mesh off
	fi
}

#add by wuwenhua for iptables filter rule error.
# Chain FORWARD (policy DROP 0 packets, 0 bytes)
#  pkts bytes target     prot opt in     out     source               destination         
#    59  3432 forwarding_rule  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3: Custom forwarding rule chain */
#     0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED /* !fw3 */
#    57  3276 reject     all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3 */
#     0     0 forwarding_rule  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3: Custom forwarding rule chain */
#     0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED /* !fw3 */
#     0     0 zone_lan_forward  all  --  br-lan *       0.0.0.0/0            0.0.0.0/0            /* !fw3 */
#     0     0 zone_wan_forward  all  --  eth1   *       0.0.0.0/0            0.0.0.0/0            /* !fw3 */
#     0     0 reject     all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3 */
check_iptable_count=20
check_iptable_looper=0
check_iptable_rule() {
    # $check_iptable_looper >= $check_iptable_count
    if [ $check_iptable_looper -ge $check_iptable_count ];then
        return
    fi

    # check_iptable_looper++
    check_iptable_looper=`expr $check_iptable_looper + 1`
    
	iptable_error=`iptables -nv -L FORWARD  | grep forwarding_rule | wc -l`
    if [ $iptable_error -gt 1 ];then 
        check_iptable_looper=$check_iptable_count
        /etc/init.d/firewall restart
        logger -t "[check_iptable]" "/etc/init.d/firewall restart"
        return
    fi
}

CULINK_VERSION="/tmp/culinkVer.log"
#if ra3 down, we need up ra3.
check_culink_cnt=0
check_culink_ra3() {

    new_version=`cat /cuLink/zeroConf/tmp/cuLinkZeroConfig.log | grep "sdk version" | awk -F ':' '{print $2}'`
    old_version=`cat $CULINK_VERSION`
    if [ "$new_version" != "$old_version" ] && [ "X$new_version" != "X" ];then
        echo $new_version > $CULINK_VERSION
    fi
    
    ra3_down_up=`ifconfig  | grep ra3 | grep HWaddr | wc -l`
        
    if [ $ra3_down_up -eq 0 ];then
        check_culink_cnt=`expr $check_culink_cnt + 1`
        if [ $check_culink_cnt -ge 3 ];then
            check_culink_cnt=0
            logger -t "[check_culink_ra3]" "/usr/bin/culink_jcg open_ra3 0"
            /usr/bin/culink_jcg open_ra3 0
        fi
    else
        check_culink_cnt=0
    fi
}

#if wifi profile is error, we need reboot.
check_wifi_conf_log="/etc/wifi_conf.debug.log"
check_wifi_profile_cnt=0
check_wifi_profile_file() {

    # isFactoryMode 1/null:enable and 0:disable, factory mode return directly
    isFactoryMode=`nvram get factory isFactoryMode 2>/dev/null`
    if [ "X$isFactoryMode" == "X1" ] || [ "X$isFactoryMode" == "X" ]; then
        check_wifi_profile_cnt=0
        return
    fi

    # If any file has less 430 lines, rebuild the configuration
    b0=`wc -l /etc/wireless/mediatek/mt7981.dbdc.b0.dat | cut -d ' ' -f 1 2>/dev/null`
    b1=`wc -l /etc/wireless/mediatek/mt7981.dbdc.b1.dat | cut -d ' ' -f 1 2>/dev/null`
    if [ $b0 -lt 430 ] || [ $b1 -lt 430 ];then
        check_wifi_profile_cnt=`expr $check_wifi_profile_cnt + 1`
        if [ $check_wifi_profile_cnt -ge 8 ];then
            check_wifi_profile_cnt=0
            echo "[`date +%m/%d@%H:%M:%S`]b0=[$b0] b1=[$b1]check_wifi_profile_file reboot." >> $check_wifi_conf_log
            logger -t "[check_wifi_profile_file]" "reboot"
            reboot
        fi
    else
        check_wifi_profile_cnt=0
    fi
}

# check agent fake meshed in following case:
# At agent side, it think self meshed ok, bh_connection_status is connected and can get mesh topo, but can't access internet.
# but at controller side, it can see agent access as 5G STA(iwpriv rax1 stainfo), but It think Agent is not meshed.
check_agent_fake_cnt=0
check_agent_fake_retry_cnt=0
check_agent_fake_meshed() {

    local inet_state=$1

    # check enable
    checkFakeEnable=`uci -q get easyMesh.checker.agentFakeMeshedCheckEnable`
    if [ "$checkFakeEnable" != "1" ]; then
        return
    fi

    # at systemup, don't do checking
    uptime=`cat /proc/uptime | cut -d '.' -f 1`
    if [ $uptime -lt 360 ]; then
        return
    fi

    # mesh process not startup
    mapd=`pidof mapd`
    p1905d=`pidof p1905_managerd`
    if [ "X$mapd" == "X" -o "X$p1905d" == "X" ]; then
        check_agent_fake_cnt=0
        return
    fi

    role=`wificonf -f /etc/map/mapd_user.cfg get DeviceRole`
    if [ "$role" != "2" ]; then
        check_agent_fake_cnt=0
        return
    fi

    bh_status=`jcg_mesh_helper.lua get_bh_connection_status`
    if [ $bh_status -eq 1 -a $inet_state -eq 0 ]; then
        check_agent_fake_cnt=`expr ${check_agent_fake_cnt} + 1`

        # get continuous fake meshed time
        check_agent_fake_MAX_cnt=`uci -q get easyMesh.checker.agentFakeMeshedTime`
        [ -z "$check_agent_fake_MAX_cnt" ] && check_agent_fake_MAX_cnt=300
        let check_agent_fake_MAX_cnt=$check_agent_fake_MAX_cnt/$MAIN_SLEEP_STEP

        # get allowed max restart times
        check_agent_fake_MAX_retry_cnt=`uci -q get easyMesh.checker.agentFakeMeshedMaxRetryCnt`
        [ -z "$check_agent_fake_MAX_retry_cnt" ] && check_agent_fake_MAX_retry_cnt=5

        # check fake meshed
        if [ $check_agent_fake_cnt -gt $check_agent_fake_MAX_cnt ]; then
            check_agent_fake_retry_cnt=`expr ${check_agent_fake_retry_cnt} + 1`
            if [ $check_agent_fake_retry_cnt -gt $check_agent_fake_MAX_retry_cnt ]; then
                echo "[mesh]restart agent $check_agent_fake_retry_cnt over $check_agent_fake_MAX_retry_cnt times, stop"
                logger -t "[mesh]" "restart agent $check_agent_fake_retry_cnt over $check_agent_fake_MAX_retry_cnt times, stop"
            else
                echo "[mesh]restart agent $check_agent_fake_retry_cnt times"
                logger -t "[mesh]" "restart agent $check_agent_fake_retry_cnt times"
                EasyMesh_openwrt.sh &
            fi
            check_agent_fake_cnt=0
        fi
    else
        check_agent_fake_cnt=0
    fi

    return
}

ping_internet_count=4  # make red led blink when internet is disconnect at system powerup.
PING_NET_MAX_COUNT=1
##################################################
##################### main #######################
##################################################
while true
do
	# internet led control
	state=$(ping_internet)
	if [ $state -eq 0 ];then
        #add by wuwenhua, ping_internet error count >=3, then led read.
		ping_internet_count=`expr $ping_internet_count + 1`
		echo "0" > /tmp/ping_internet        #add by wuwenhua,for mqttagent
    elif [ $state -eq 2 ];then
        ping_internet_count=$PING_NET_MAX_COUNT
        echo "0" > /tmp/ping_internet        #add by wuwenhua,for mqttagent
	else
        ping_internet_count=0
        echo "1" > /tmp/ping_internet        #add by wuwenhua,for mqttagent
	fi
	#echo "state=$state, ping_internet_count=$ping_internet_count, last_inet_state=$last_inet_state."
	if [ $state -eq 1 -a $last_inet_state -ne 1 ];then
		/usr/bin/led_ctl green on
		/usr/bin/led_ctl red off
		last_inet_state=$state
	elif [ $state -eq 0 -a $last_inet_state -ne 0 -a $ping_internet_count -ge $PING_NET_MAX_COUNT ] || [ $state -eq 2 -a $last_inet_state -ne 2 ];then
		logger -t "[wan]" "red led blink($ping_internet_count)"
		/usr/bin/led_ctl green off

		#
		# if same board different product have different spec, 
		# should use /etc/productInfo.boardModel
		#
		if [ "$boardModel" == "PK964M" -o "$boardModel" == "AX618M" ]; then
			/usr/bin/led_ctl red blink 500 500
		elif [ "$boardModel" == "PK963M" -o "$boardModel" == "PK968M" -o "$boardModel" == "PK970M" ]; then
			/usr/bin/led_ctl red on
		else
			/usr/bin/led_ctl red blink 500 500
		fi
		last_inet_state=$state
	fi
	
    sleep $MAIN_SLEEP_STEP
done
