#!/bin/sh

#
# App : AutoDisconnect
# Url : https://garage.maemo.org/projects/autodisconnect/
# Version: 0.3
# Author: Aymeric Brisse <aymeric.brisse@gmail.com>
# License: GNU General Public License
#

# ---------------------------------------------------------------------------
# FUNCTIONS
# ---------------------------------------------------------------------------

# ---------------------------------------------------------------------------
readparameters()
# ---------------------------------------------------------------------------
{
    # How often to test for inactivity (min)
    g_samplerate="`gconftool-2 -g /apps/autodisconnect/param_interval`"

    # Enable logging
    g_logging="true"

    # Notifications
    g_notifications="`gconftool-2 -g /apps/autodisconnect/param_notifications`"

    # Number of bytes allowed to be received without disconnect
    g_dontcountbytespermin="`gconftool-2 -g /apps/autodisconnect/param_min_bytes`"

    # Exceptions
    g_exceptions=
    [[ "`gconftool-2 -g /apps/autodisconnect/param_exception_ssh`" = true ]] && g_exceptions="ssh "$g_exceptions

    # Network Interfaces to check
    g_enable=
    [[ "`gconftool-2 -g /apps/autodisconnect/param_connection_wlan`" = true ]] && g_enable="wlan "$g_enable
    [[ "`gconftool-2 -g /apps/autodisconnect/param_connection_gprs`" = true ]] && g_enable="gprs "$g_enable

    # Where to store the logfile. This is cleared when it goes over 50k.
    logfile=/var/log/autodisconnect.log

    # Number of bytes to ignore for each time period
    g_dontcountbytes=$((g_dontcountbytespermin*g_samplerate))

    # Convert min interval to sec interval
    g_samplerate=$((g_samplerate*60))
}

# ---------------------------------------------------------------------------
init()
# ---------------------------------------------------------------------------
{
    # Log monitor startup to file
    logentry "<Start>"

    # Kill every instances already running

    TmpFile=/tmp/$(basename $0).tmp

    `ps | egrep 'S[ ]*/bin/sh[ ]*/opt/autodisconnect/autodisconnect-network' | sed 's/^[ ]*\([0-9]*\) .*$/\1/g' > $TmpFile`

    while read Pid
    do
        [[ -n "$Pid" -a "$Pid" -ne "$$" ]] && {
            logentry "<Kill $Pid>"
            kill -KILL $Pid
        }
    done < $TmpFile

    # Allow dbus to work
    [[ -e /tmp/dbus-info ]] && eval `cat /tmp/dbus-info`

    export DBUS_SESSION_BUS_ADDRESS \
           DBUS_SESSION_BUS_PID \
           DBUS_SESSION_BUS_WINDOWID

    # Don't let log file get too big
    if [[ -w "$logfile" ]]; then
        size=`stat $logfile | grep Size | awk '{ print $2; }'`
        [[ "$size" -gt 50000 ]] && :>$logfile
    fi

    # Waiting for possible closing connections
    # Waiting for initial traffic to be made -> then the next check will close the connection if idle
    sleep 30
}

# ---------------------------------------------------------------------------
logentry()
# ---------------------------------------------------------------------------
# Send a string to this function to append it to the log file
#
# Arg 1 - The text to log
{
    [[ "$g_logging" = "true" ]] && {
        echo -e "[`date +%T`][$$][Network] $1" >> $logfile
    }
}

# ---------------------------------------------------------------------------
osnotify()
# ---------------------------------------------------------------------------
# Send a string to this function to generate a system popup
#
# Arg 1 - The text to display
{
    [[ "$g_notifications" = "true" ]] && {
		/usr/bin/dbus-send --type=method_call \
			--dest=org.freedesktop.Notifications \
			/org/freedesktop/Notifications \
			org.freedesktop.Notifications.SystemNoteInfoprint \
			string:"$1"
	}
}

# ---------------------------------------------------------------------------
disconnect()
# ---------------------------------------------------------------------------
# Disconnect current connection
#
# No args
{
    dbus-send --system --dest=com.nokia.icd \
        /com/nokia/icd_ui \
        com.nokia.icd_ui.disconnect \
        boolean:true
}

# ---------------------------------------------------------------------------
disable_quit()
# ---------------------------------------------------------------------------
# Disabled for some interfaces
#
{
    short_interface=`echo "$interface" | tr -d 0-9`
    connection_check=`echo "$g_enable" | grep "$short_interface" 2>/dev/null`
    
	if [[ -n "$short_interface" -a -n "$connection_check" ]]; then
		osnotify "AutoDisconnect is now running"
		logentry "$interface started"
	else
		logentry "$interface ignored"
        logentry "<Stop>"
		exit 0
	fi
}

# ---------------------------------------------------------------------------
main()
# ---------------------------------------------------------------------------
# Main entry point
#
{
    # Read parameters
    readparameters

    # Init -> Kill other instances & dbus & log & sleep
    init

    # Get interface
    	
	interface=$IFACE
	
	if [[ -z "$interface" ]]; then
		# gprs0 generally
		interface="`grep gprs0 /proc/net/route | tail -1 | cut -f1`"
	fi

    # Quit if this interface doesn't have to be checked
    disable_quit
	
	packets_before="`grep $interface /proc/net/dev | awk -F":" '{print $2}' | awk '{print $1}'`"
	
	#PERFORM MAIN MONITORING LOOPS
	while true
	do
		sleep $g_samplerate

        # Check if connection is still alive

        interface_check="`grep $interface /proc/net/route | tail -1 | cut -f1`"

        [[ -z "$interface_check" ]] && {
            logentry "$interface closed (externally)"
            break
        }

        # Check if no exception service is running

        exception_apply=false

        if [[ -n "$g_exceptions" ]]; then

            my_ip="`ifconfig "$interface" | grep "inet addr" | sed 's/^[ ]*inet addr:\([0-9\.]*\) .*$/\1/g'`"

            for exception in $g_exceptions ; do
                exception_check="`netstat | grep :$exception | grep ESTABLISHED | grep $my_ip`"
                [[ -n "$exception_check" ]] && exception_apply=true && logentry "$interface checked ($exception)" && break
            done

        fi

        # Check if the phone is charging

        charging_status="`lshal -u '/org/freedesktop/Hal/devices/bme' | grep battery.rechargeable.is_charging | awk '{print $3}'`"

        if [[ $g_running_options = 2 -a $charging_status = true ]]; then
          exception_apply=true && logentry "$interface checked (phone_charging)"
        fi

        # Check the traffic volume

		packets_after="`grep $interface /proc/net/dev | awk -F":" '{print $2}' | awk '{print $1}'`"

		if [[ "$exception_apply" = false -a "$packets_after" -lt "$((packets_before+g_dontcountbytes))" ]]; then
			disconnect
			osnotify "AutoDisconnect has closed the inactive connection"
			logentry "$interface closed (inactive) +$((packets_after-packets_before))"
			break
		else			
			logentry "$interface checked (+$((packets_after-packets_before)))"
			packets_before=$packets_after   
		fi

	done
	
}

# ---------------------------------------------------------------------------
# RUNTIME
# ---------------------------------------------------------------------------

# Start AutoDisconnect

g_running_options="`gconftool-2 -g /apps/autodisconnect/param_running_options`"
[[ $g_running_options != 0 ]] && main && logentry "<Stop>"

exit 0

