#!/bin/bash
#
#       /etc/rc.d/init.d/nsc
#
#       The FreeSwitch Open Source Voice Platform
#
#  chkconfig: 345 89 14
#  description: Starts and stops the freeswitch server daemon
#  processname: freeswitch
#  config: /opt/freeswitch/conf/freeswitch.conf
#  pidfile: /opt/freeswitch/run/freeswitch.pid
#

# Source function library.
. /etc/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

# Source auto-configure functions
[ -e /etc/init.d/functions-automagic ] && source /etc/init.d/functions-automagic
[ -e /etc/sysconfig/automagic ] && source /etc/sysconfig/automagic

PROG_NAME=nsc
MEMPRELOADER=${MEMPRELOADER-/usr/local/bin/malloc-preloader}
PID_FILE=${PID_FILE-/usr/local/nsc/run/freeswitch.pid}
FS_USER=${FS_USER-root}
FS_FILE=${FS_FILE-/usr/local/nsc/bin/nsc}
FS_HOME=${FS_HOME-/usr/local/nsc}
FS_LOG_CORE=${FS_HOME}/log/core.log
FS_LOG_FILE=/var/log/nsc/nsc.log
LOCK_FILE=/var/lock/subsys/nsc
NSC_ARGS="-ncwait -nonat -nocal -rp"
RETVAL=0
VOCMAC=""
CLEAN_LOOP=30
RECOVER_LOOP=30

# Source options file
if [ -f /etc/sysconfig/nsc ]; then
    . /etc/sysconfig/nsc
fi

# Source override options
if [ -f /etc/sysconfig/nsc.override ]; then
    . /etc/sysconfig/nsc.override
fi

# <define any local shell functions used by the code that follows>

FS_TMPFS_ENABLE="YES"
FS_TMPFS_LOG_DIR=/var/log/nsc
FS_TMPFS_LOG_ARCHIVE=${FS_HOME}/log_archive
FS_TMPFS_LOG_ARCHIVE_LIMIT=10

FS_TMPFS_DATA_DIR=${FS_HOME}/data
FS_TMPFS_CDR_BASE=data/xml_cdr
FS_TMPFS_CDR_DIR=${FS_HOME}/${FS_TMPFS_CDR_BASE}

FS_TMPFS_SIZE_LIMIT=536870912 # 512 mb
FS_TMPFS_ARCHIVE_LIMIT=10

cleanup_tmpfs_helper() {
    count=$FS_TMPFS_ARCHIVE_LIMIT

    while [ "$count" != "0" ]; do
        if ! read; then return 0; fi
        count=$(($count-1))
    done

    while read dir; do
        rm -rf "$FS_TMPFS_LOG_ARCHIVE/${dir}"
    done
}

cleanup_tmpfs() {
    find "$FS_TMPFS_LOG_ARCHIVE" -mindepth 1 -maxdepth 1 -type d -printf '%P\n' | \
        sort -rn | cleanup_tmpfs_helper
}

backup_tmpfs_helper() {
    tmstamp=`date '+%F.%H-%M-%S'`
    destdir="$FS_TMPFS_LOG_ARCHIVE/${tmstamp}"

    while read file; do
        filedir=`dirname "$file"`
        mkdir -p "${destdir}/${filedir}"
        cp -u "$FS_TMPFS_LOG_DIR/$file" "${destdir}/${file}"
    done
}

backup_tmpfs() {
    find "$FS_TMPFS_LOG_DIR" -name '*.log*' -printf '%P\n' | backup_tmpfs_helper

    cleanup_tmpfs
}

setup_tmpfs() {
    if [ ! -e "$FS_TMPFS_CDR_DIR" ]; then
        if [ ! -e "${FS_TMPFS_LOG_DIR}/xml_cdr" ]; then
            mkdir -p "$FS_TMPFS_CDR_DIR" && \
                chown webconfig:root "$FS_TMPFS_DATA_DIR" && chmod 0750 "$FS_TMPFS_DATA_DIR" && \
                chown webconfig:root "$FS_TMPFS_CDR_DIR"  && chmod 0750 "$FS_TMPFS_CDR_DIR"

        elif [ ! -h "${FS_TMPFS_LOG_DIR}/xml_cdr" ]; then
            mkdir -p "$FS_TMPFS_DATA_DIR" && \
                chown webconfig:root "$FS_TMPFS_DATA_DIR" && chmod 0750 "$FS_TMPFS_DATA_DIR" && \
                mv "${FS_TMPFS_LOG_DIR}/xml_cdr" "$FS_TMPFS_CDR_DIR"
        fi
    fi

    if [ ! -h log ] ; then
        ln -fs . log
    fi

    if [ ! -h xml_cdr ]; then
        ln -fs ../${FS_TMPFS_CDR_BASE} xml_cdr
    fi
}

enable_tmpfs() {
    if [ ! -e "$FS_TMPFS_LOG_DIR" ]; then
        mkdir -p "$FS_TMPFS_LOG_DIR"
    fi

    if [ ! -e "$FS_TMPFS_LOG_ARCHIVE" ]; then
        mkdir -p "$FS_TMPFS_LOG_ARCHIVE"
    fi

    backup_tmpfs

    if ! grep -q $FS_TMPFS_LOG_DIR /proc/mounts; then
        webuid=`awk -F: '/^webconfig:/ { print $3 }' /etc/passwd 2>/dev/null`
        mount -t tmpfs -o mode=0750,uid=$webuid,gid=0,size=$FS_TMPFS_SIZE_LIMIT none "$FS_TMPFS_LOG_DIR" || return 1

    fi

    [ ! -f "$FS_LOG_CORE" ] && touch "$FS_LOG_CORE"

    ln -sf "$FS_LOG_CORE" "/var/log/core-nsc.log"

    #(cd "$FS_TMPFS_LOG_DIR" && setup_tmpfs)
}

disable_tmpfs_helper() {
    if [ ! -h log ] ; then
        ln -fs . log
    fi
}

disable_tmpfs() {
    if ! grep -q $FS_TMPFS_LOG_DIR /proc/mounts; then
        return 0
    fi

    backup_tmpfs

    umount "$FS_TMPFS_LOG_DIR" || return 1

    (cd "$FS_TMPFS_LOG_DIR" && disable_tmpfs_helper)
}

enable_dnsmasq() {

    #check if dnsmasq already enabled
    DNSMASQ_STATUS=`grep 'nameserver 127.0.0.1' /etc/resolv.conf`

    if [ -z "$DNSMASQ_STATUS" ]; then
        awk -F' ' '{ if ($1 == "nameserver") { print > "/etc/resolv.dnsmasq.new" } else { print > "/etc/resolv.conf.new" } }' /etc/resolv.conf && \
            touch /etc/resolv.conf.new /etc/resolv.dnsmasq.new  && \
            echo 'nameserver 127.0.0.1' >> /etc/resolv.conf.new && \
            mv -f /etc/resolv.conf.new /etc/resolv.conf         && \
            mv -f /etc/resolv.dnsmasq.new /etc/resolv.dnsmasq
    fi

    service dnsmasq restart > /dev/null 2>&1

}

disable_dnsmasq() {

    #check if dnsmasq already enabled
    DNSMASQ_STATUS=`grep 'nameserver 127.0.0.1' /etc/resolv.conf`

    if [ ! -z "$DNSMASQ_STATUS" ]; then
        grep -v '^nameserver' /etc/resolv.conf > /etc/resolv.conf.new
        cat /etc/resolv.dnsmasq >> /etc/resolv.conf.new
        mv -f /etc/resolv.conf.new /etc/resolv.conf
    fi

}

dump_log_errors()
{
    cat "$FS_LOG_CORE" "$FS_LOG_FILE" 2>/dev/null | \
        grep '\[ALERT\|CRIT\|ERR\]' | \
            sed -e 's/\(.\+\)[.][0-9]+ \(\[[A-Z]+\]\) [^ ]\+ \(.\+\)/(\1) \2 \3/'
    echo
}

start() {
    #let us start rtcpmon
    MYSTATUS=$(service rtcpmon status)

    if [ $NSC_RTCPMON_ENABLE = "true" ] && [[ $MYSTATUS != *running* ]]
    then
        service rtcpmon start
    fi

    #let us start sipsecmon
    MYSTATUS=$(service sipsecmon status)

    if [ $NSC_SIPSECMON_ENABLE = "true" ] && [[ $MYSTATUS != *running* ]]
    then
        service sipsecmon start
    fi

    #let us start mediamon
    MYSTATUS=$(service mediamon status)

    if [ $NSC_MEDIAMON_ENABLE = "true" ] && [[ $MYSTATUS != *running* ]]
    then
        service mediamon start
    fi

    echo -n "Starting $PROG_NAME: "
    if [ -e $LOCK_FILE ]; then
        if [ -e $PID_FILE ] && [ -e /proc/`cat $PID_FILE` ]; then
            echo
            echo -n $"$PROG_NAME is already running.";
            failure $"$PROG_NAME is already running.";
            echo
            return 1
        fi
    fi

    if [ "$FS_TMPFS_ENABLE" != "YES" ]; then
        disable_tmpfs
    else
        enable_tmpfs || echo "WARNING: unable to enable tmpfs optimization"
    fi

    cd $FS_HOME

    # Make sure core file size is not limited   
    ulimit -c unlimited
    daemon --user $FS_USER --pidfile $PID_FILE "$MEMPRELOADER $FS_FILE $NSC_ARGS $NSC_PARAMS >/dev/null 2>&1"
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && touch $LOCK_FILE;
    echo

    if [ $RETVAL -ne 0 ]; then
        [ -f "$FS_LOG_CORE" -o -f "$FS_LOG_FILE" ] && dump_log_errors
    fi

    return $RETVAL
}

stop() {
    echo -n "Shutting down $PROG_NAME: "
    if [ ! -e $LOCK_FILE ]; then
        echo
        echo -n $"cannot stop $PROG_NAME: $PROG_NAME is not running."
        failure $"cannot stop $PROG_NAME: $PROG_NAME is not running."
        echo
        return
    fi
    cd $FS_HOME
    $FS_FILE -stop > /dev/null 2>&1
    killproc -d 15 $PROG_NAME
    RETVAL=$?
    if [ $RETVAL -ne 0 ]; then
        echo -n $"stopping $PROG_NAME failed (ret=$RETVAL), trying again..."
        killproc -d 2 $PROG_NAME
        RETVAL=$?

        if [ $RETVAL -ne 0 ]; then
            echo -n $"stopping $PROG_NAME failed (ret=$RETVAL)"
        fi
    fi

    echo
    [ $RETVAL -eq 0 ] && rm -f $LOCK_FILE;

    #let us stop rtcpmon
    MYSTATUS=$(service rtcpmon status)

    if [[ $MYSTATUS == *running* ]]
    then
        service rtcpmon stop
    fi

    #let us stop sipsecmon
    MYSTATUS=$(service sipsecmon status)

    if [[ $MYSTATUS == *running* ]]
    then
        service sipsecmon stop
    fi

    #let us stop mediamon
    MYSTATUS=$(service mediamon status)

    if [[ $MYSTATUS == *running* ]]
    then
        service mediamon stop
    fi

    if [ "$FS_TMPFS_ENABLE" = "YES" ]; then
        backup_tmpfs
    fi

    return $RETVAL
}

# arg 1: service name
forcestop() {

    service_pid=`pidof $1`
    if [[ ! -z "$service_pid" ]]; then
        if [[ ! -z $LOCK_FILE ]]; then
            rm -f "$LOCK_FILE"
        fi
        kill -9 $service_pid
        echo "service $1 has been force stopped"
    else
        echo "service $1 already stopped"
    fi

    if [ "$FS_TMPFS_ENABLE" = "YES" ]; then
        backup_tmpfs
    fi
}


# arg 1: service name
cleanup() {

    service_pid=`pidof $1`
    if [[ ! -z "$service_pid" ]]
    then
        echo "forcing service $1 to stop before cleaning up."
        service $1 forcestop
    fi

    if [[ ! -z $LOCK_FILE ]]; then
        rm -f "$LOCK_FILE"
        echo "removed lock file $LOCK_FILE"
    fi

    if [ "$FS_TMPFS_ENABLE" = "YES" ]; then
        backup_tmpfs
    fi
}

# service1 service pid
showstats(){
    STATS=(`ps --no-headers -o pcpu,rss,etime $1`)
    echo "CPU Usage: ${STATS[0]} %, Memory Usage: ${STATS[1]} KB, Uptime: ${STATS[2]}"
}

# arg 1: service name
sngstatus() {

    service_pid=`pidof $1`
    if [[ ! -z "$service_pid" ]]; then
        if [[ -f "$LOCK_FILE" ]]; then
            echo "service $1 is running" 
        else
            echo "service $1 is stopping, please wait."
        fi
        showstats $service_pid
        return 0
    else
        echo "service $1 is stopped"
        return 3
    fi
}

silentstatus() {
    service_pid=`pidof $1`
    if [[ ! -z "$service_pid" ]]; then
        return 0
    else
        return 3
    fi
}

rhstatus() {
    sngstatus $PROG_NAME;
}

recover() {
    c=1
    stat=0
    while (( $c <= $RECOVER_LOOP )); do
        silentstatus $PROG_NAME
        stat=$?
        if (( stat == 3 )); then
            start
            break
        else
            sleep 1
            (( c++ ))
        fi
    done
}

voccleanup() {
    if [ -n "$EXTIF" ]; then

        for INTERFACE in $EXTIF; do

            MACWORD=$(ifconfig $INTERFACE | grep HWaddr)
            VOCMAC=$(awk -v MACSTR="$MACWORD" 'BEGIN {i=index(MACSTR, "HWaddr"); print substr(MACSTR, i+7, 17)}')

            [[ "$VOCMAC" != "02:19:23"* ]] && continue

            #let's wait for nsc stop and clean up vocallo
            c=1
            stat=0
            while (( $c <= $CLEAN_LOOP )); do
                silentstatus $PROG_NAME
                stat=$?
                if (( stat == 3 )); then
                    echo -n "Resetting Media Server:"
                    /usr/local/nsc/bin/sngtc_tool -dev $INTERFACE -reset
                    echo "                                    [  OK  ]"
                    break
                else
                    sleep 1
                    (( c++ ))
                fi
            done

            #if media server not stopped in 30 seconds, force to stop
            if (( $c > $CLEAN_LOOP )); then
                forcestop $PROG_NAME
                break
            fi

        done

    fi
}

case "$1" in
    start)
    enable_dnsmasq
    start
    ;;
    stop)
    stop
    disable_dnsmasq
    ;;
    status)
    sngstatus $PROG_NAME
    RETVAL=$?
    ;;
    cleanup)
    cleanup $PROG_NAME
    ;;
    forcestop)
    forcestop $PROG_NAME
    ;;
    restart)
    stop
    enable_dnsmasq
    start
    ;;
    recover)
    recover
    ;;
    condrestart)
    [ -f $PID_FILE ] && restart || :
    ;;
    *)
    echo "Usage: $PROG_NAME {start|stop|status|restart|forcestop|cleanup}"
    exit 1
    ;;
esac
exit $RETVAL
