#!/bin/sh
# CTM-ONE Cell manager script w/o qstats

# User Variables
#CONN_CHK_PERIOD determines how many seconds to wait before querying network/connection status from SYSDB
CONN_CHK_PERIOD=5
#CONN_TIMEOUT is the connection timeout in seconds. Once this is reached, ql-dial will be restarted
CONN_TIMEOUT=60
#set MAX_QL_DIAL_ERR to -1 to always exit after ql-dial exits, 0 if don't want to exit script once limit reached
MAX_QL_DIAL_ERR=2
#set 0 to disable waiting for registration, else seconds to wait before exiting script
WAIT_REGISTRATION=900
#set to non blank (e.g. "1") to always start with that profile by default
PROFILE=""
#ql-dial args
QL_DIAL_ARGS="-f raw-ip -U /usr/bin/udhcpc_override -d ${CONN_TIMEOUT}"

# System Variables
APN="iot.cypress.iot"
QL_DIAL_ERR_CNT=0
LOC_QL_DIAL_ERR_CNT=0
#FWL-2533 CELL_DEV="/dev/ttyUSB2"
CELL_DEV="/dev/ttyQSB2"
FAIL_CNT_FILE="/tmp/fail.cnt"
CLEAR_FAIL_CNT="/tmp/fail.clear"
QTEL_STATS_CLEAR_STATS="/tmp/qstats.clear"
CELL_MAN_PID_FILE="/var/run/cell_man.pid"
CELL_MAN_KILL_FILE="/tmp/cell_man.kill"
CELL_MAN_EXIT_FILE="/tmp/cell_man.exit"
CELL_MAN_EXIT_CODE_FILE="/tmp/cell_man.exitcode"
QSTATS_PID_FILE="/var/run/qstats_cli.pid"
QSTATS_PID=0
RSYSLOG_ID="cell"
RSYSLOG_FACILITY="local0"
DO_NOT_DIAL=0

dbg_logger()
{
    logger -p ${RSYSLOG_FACILITY}.$1 -t ${RSYSLOG_ID} cell_man: $2
}

sigterm_handler()
{
    dbg_logger "notice" "Captured sigterm"
    touch ${CELL_MAN_EXIT_FILE}
}

trap sigterm_handler SIGINT
trap sigterm_handler SIGQUIT
trap sigterm_handler SIGTERM

clear_qstats()
{
    dbg_logger "info" "Clearing qstats"
    touch ${QTEL_STATS_CLEAR_STATS}
}

start_qstats_poll()
{
    dbg_logger "info" "Start qstats polling"
    /bin/touch /tmp/qstats.running
}

stop_qstats()
{
    dbg_logger "info" "Stopping qstats polling"
    /bin/rm -f /tmp/qstats.running
}

wrap_up_and_exit()
{
    dbg_logger "info" "exiting with code $1"
    stop_qstats
    killall -9 ql-dial
    case $1 in
    0|9)
        echo "0" > ${CELL_MAN_EXIT_CODE_FILE}
        ;;
    *)
        echo "-1" > ${CELL_MAN_EXIT_CODE_FILE}
        ;;
    esac
    rm ${CELL_MAN_PID_FILE}
    exit $1
}

chk_exit()
{
    if [ -e "${CELL_MAN_KILL_FILE}" ]; then
        dbg_logger "notice" "kill cell_man service requested"
        rm ${CELL_MAN_KILL_FILE}
        wrap_up_and_exit 97
    fi
    if [ -e "${CELL_MAN_EXIT_FILE}" ]; then
        dbg_logger "notice" "cell_man service exit requested"
        rm ${CELL_MAN_EXIT_FILE}
        wrap_up_and_exit 0
    fi
}

vzw_backoff()
{
    DELAY=0
    case $1 in
    0)
        ;;
    1)
        ;;
    2)
        ;;
    3)
        DELAY=15
        ;;
    4)
        DELAY=120
        ;;
    5)
        DELAY=480
        ;;
    *)
        DELAY=900
        ;;
    esac
    dbg_logger "alert" "Dialer delay=${DELAY}"
    CNT=0
    while [ ${CNT} -lt ${DELAY} ];
    do
        let CNT=CNT+1
        sleep 1
        chk_exit
    done
}

while [ $DO_NOT_DIAL -eq 1 ]; do
    dbg_logger "info" "Dialer is idling"
    chk_exit
    sleep 5
done

if [ "$1" = "apn" ]; then
    APN="$2"
else
    PROFILE="$2"
fi

if [ ${#PROFILE} -gt 0 ]; then
    dbg_logger "notice" "Using profile ${PROFILE}"
else
    dbg_logger "notice" "Using apn ${APN}"
fi

if [ -e "${CLEAR_FAIL_CNT}" ]; then
    rm ${FAIL_CNT_FILE}
    rm ${CLEAR_FAIL_CNT}
else
    if [ -e "${FAIL_CNT_FILE}" ]; then
        QL_DIAL_ERR_CNT=$(cat ${FAIL_CNT_FILE})
    fi
fi

dbg_logger "notice" "Starting with fail cnt ${QL_DIAL_ERR_CNT}"
start_qstats_poll
while :
do
    chk_exit
    # Wait until cell port is powered up
    dbg_logger "info" "Checking cell port is up"
    while :
    do
        chk_exit
        sleep 2
        if [ -e "${CELL_DEV}" ]; then
            echo "Cell device found, starting dialer"
            sleep 2
            break;
        fi
    done

    # Start qmi-proxy
    dbg_logger "info" "Starting qmi-proxy and clear CIDs"
    qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength -p --device-open-sync
    if [ $? -ne 0 ]; then
        dbg_logger "notice" "qmi-proxy error, retrying"
        qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength -p --device-open-sync
        if [ $? -ne 0 ]; then
            dbg_logger "notice" "qmi-proxy error, exiting dialer"
            wrap_up_and_exit 98
        fi
    fi

    # Wait a bit
    sleep 5

    # See wait for qstats to finish clearing values
    while [ -e "${CLEAR_QSTATS}" ]; do
        dbg_logger "debug" "waiting for qstats to clear values"
        sleep 1
    done

    REGISTRATION_CNT=0
    # see if need to wait for registration
    while [ ${WAIT_REGISTRATION} -gt 0 ]; do
        chk_exit
        dbg_logger "debug" "Waiting for registration"
        REGISTERED=$(cmd sysdb get CELL_REGISTERED | grep CELL_REGISTERED | awk -F= '{print $2}')
        if [ ${#REGISTERED} -le 0 ]; then
            REGISTERED=-1
        elif [ ${REGISTERED} -eq 1 ]; then
            break
        fi
        sleep 2
        let REGISTRATION_CNT=REGISTRATION_CNT+2
        if [ ${REGISTRATION_CNT} -ge ${WAIT_REGISTRATION} ]; then
            dbg_logger "notice" "exit due to registration timeout"
            wrap_up_and_exit 99
        fi
    done

    echo 1 > /sys/class/net/wwan0/qmi/raw_ip
    # Start dialer, which blocks until disconnect/error
    dbg_logger "info" "Starting ql-dial"
    if [ ${#PROFILE} -gt 0 ]; then
        ql-dial ${QL_DIAL_ARGS} -P ${PROFILE} &
    else
        ql-dial ${QL_DIAL_ARGS} -a ${APN} &
    fi
    QL_DIAL_PID=$!
    TIME_DISCONNECTED=0
    GOT_IP=0
    REGISTERED=0
    CONNECTED=0
    # Monitor ql-dialer
    while :
    do
        chk_exit
        sleep ${CONN_CHK_PERIOD}

        # If count file no longer exists, then it's cleared by udhcpc
        if [ ! -e "${FAIL_CNT_FILE}" ]; then
                QL_DIAL_ERR_CNT=0
                LOC_QL_DIAL_ERR_CNT=0
        fi

        # See if PID still exists
        dbg_logger "info" "Checking ql-dial"
        kill -0 ${QL_DIAL_PID}
        if [ $? -eq 0 ]; then
            # Check CELL_CONNECTED and CELL_REGISTERED. If not registered or connected for CONN_TIMEOUT, kill ql-dial (assume it hung)
            let TIME_DISCONNECTED=TIME_DISCONNECTED+${CONN_CHK_PERIOD}
            CUR_DATA=$(cmd sysdb get CELL_REGISTERED CELL_CONNECTED)

            REGISTERED=$(echo "${CUR_DATA}" | grep CELL_REGISTERED | awk -F= '{print $2}')
            if [ ${#REGISTERED} -le 0 ]; then
                REGISTERED=-1
            fi
            CONNECTED=$(echo "${CUR_DATA}" | grep CELL_CONNECTED | awk -F= '{print $2}')
            if [ ${#CONNECTED} -lt 0 ]; then
                CONNECTED=-1
            elif [ ${CONNECTED} -eq 1 ]; then
                TIME_DISCONNECTED=0
                GOT_IP=1
            fi

            dbg_logger "debug" "SYSDB:REG=${REGISTERED},CON=${CONNECTED},DISC_TIME=${TIME_DISCONNECTED},TIMEOUT=${CONN_TIMEOUT},IP=${GOT_IP}"
            if [ ${TIME_DISCONNECTED} -gt ${CONN_TIMEOUT} ]; then
                dbg_logger "notice" "Timeout occurred, killing ql-dial"
                clear_qstats
                kill -9 ${QL_DIAL_PID}
                # break to top loop to redial
                break
            fi
        else
            # ql-dial has exited, get exit code
            wait ${QL_DIAL_PID}
            QL_DIAL_EXIT_CODE=$?
            clear_qstats
            if [ ${GOT_IP} -eq 1 ]; then
                QL_DIAL_ERR_CNT=0
                LOC_QL_DIAL_ERR_CNT=0
            else
                let QL_DIAL_ERR_CNT=QL_DIAL_ERR_CNT+1
                let LOC_QL_DIAL_ERR_CNT=LOC_QL_DIAL_ERR_CNT+1
            fi
            echo ${QL_DIAL_ERR_CNT} > ${FAIL_CNT_FILE}
            dbg_logger "info" "ql-dial exited with code ${QL_DIAL_EXIT_CODE}, cnt:${LOC_QL_DIAL_ERR_CNT}, totcnt:${QL_DIAL_ERR_CNT}"

            # Error code 13 is defined in qld-globals (#define ERR_START_WWAN_OMA 13)
            # This error indicates there is likly a OMA DM session open and needs to be closed.
            if [ ${QL_DIAL_EXIT_CODE} -eq 13 ]; then
                qtel-cli -t 20 at+qodm=\"dme\",2,\"kill\"
                sleep 2
                qtel-cli -t 20 at+qodm=\"comm\",2,\"0\"
                sleep 2
            fi
            

            vzw_backoff ${QL_DIAL_ERR_CNT}
            if [ ${MAX_QL_DIAL_ERR} -eq -1 ]; then
                dbg_logger "notice" "quitting cell_man after each ql-dial exit"
                wrap_up_and_exit ${QL_DIAL_EXIT_CODE}
            elif [ ${MAX_QL_DIAL_ERR} -gt 0 ] && [ ${LOC_QL_DIAL_ERR_CNT} -gt ${MAX_QL_DIAL_ERR} ]; then
                dbg_logger "notice" "ql-dial exit error exceeded (${LOC_QL_DIAL_ERR_CNT}), quitting cell_man"
                wrap_up_and_exit ${QL_DIAL_EXIT_CODE}
            fi
            break
        fi
    done
done
