#!/bin/sh
#written by ecaddict, distributed (conveyed) under GPL version 3 or any later version

CONFIG="/opt/etc/rtorrent.conf"
BASE="/opt/share/torrent"
SRNAME=rtorrent
#user editable part end

NAME=rtorrent
EXEC=/opt/bin/$NAME
EXSC=/opt/bin/screen
EXSD=/bin/sed
EXPS=/opt/bin/ps
OPTIONS="-n -o import=${CONFIG}"
WANIF=$(nvram get wan_ifname)

getsession() echo $($EXSD -n 's/session[^\/]*\(\/.*\)/\1/p' $CONFIG)
getprange() echo $($EXSD -n 's/port_range[^0-9-]*\([0-9-]\)/\1/p' $CONFIG | $EXSD 's/-/ /')
getdhtport() echo $($EXSD -n 's/^dht_port[^0-9]*\([0-9]\)/\1/p' $CONFIG)
fwmod() {
  iptables ${1} INPUT -i "$WANIF" -p tcp --dport ${2} -j ACCEPT
}

checkcnfg() {
  ! [ -x "$EXSC" ] && EXSC=$(echo $(type screen) | $EXSD -n 's/[^\/]*\(\/.*\)/\1/p')
  if ! [ -x "$EXSC" ]; then
    logger -t $NAME "screen not found."
    echo -e "\033[1;31mScreen ($EXSC) not found, try: ipkg install screen\033[0m"
    exit 1
  fi
  ! [ -x "$EXEC" ] && EXEC=$(echo $(type rtorrent) | $EXSD -n 's/[^\/]*\(\/.*\)/\1/p')
  if ! [ -x "$EXEC" ]; then
    logger -t $NAME "rtorrent not found."
    echo -e "\033[1;31mrtorrent ($EXEC) not found, try: ipkg install rtorrent\033[0m"
    exit 2
  fi
  if ! [ -r "${CONFIG}" ] ; then 
    echo -e "\033[1;31mConfig file ${CONFIG} not found, please create it\033[0m"
    logger -t $NAME "cannot find readable config $CONFIG"
    exit 3 
  fi 
  SESSION=$(getsession "$CONFIG")
  if ! [ -d "${SESSION}" ] ; then
    echo -e "\033[1;31mSession directory $SESSION set in ${CONFIG} does not exist\033[0m"
    logger -t $NAME "cannot find readable session directory $SESSION from config $CONFIG"
    exit 4
  fi
}

fwopen() {
  DHT_PORT=$(getdhtport "$CONFIG")
  PORTS=$(seq $(getprange "$CONFIG"))
  for P in $PORTS; do
    [ -z "$(iptables -nL | grep 'dpt:'$P)" ] && fwmod -I $P
  done
  if [ "$DHT_PORT" ]; then
    [ -z "$(iptables -nL | grep 'dpt:'$DHT_PORT)" ] && fwmod -I $DHT_PORT
  fi
}

fwclose() {
  DHT_PORT=$(getdhtport "$CONFIG")
  PORTS=$(seq $(getprange "$CONFIG"))
  for P in $PORTS; do
    fwmod -D $P
  done
  if [ "$DHT_PORT" ]; then
    fwmod -D $DHT_PORT
  fi
}

d_start() {
  [ -d "${BASE}" ] && cd "${BASE}"
   SESSION=$(getsession "$CONFIG")
   if [ -s ${SESSION}/rtorrent.lock ] ; then
     LFC="$(cat ${SESSION}/rtorrent.lock)" && PID=${LFC##*+}
     if [ -n "$($EXPS -A | $EXSD -n '/'$PID' .*rtorrent/p')" ]; then
       echo -e "\033[1;33mrtorrent runs already\033[0m"
       return
     else
       echo -e "\033[1;33mrtorrent did not terminate cleanly, cleaning up\033[0m"
       rm -f ${SESSION}/rtorrent.dht_cache
       rm -f ${SESSION}/rtorrent.lock
     fi
   fi
   fwopen
   stty stop undef && stty start undef
   $EXSC -ls | grep ".$SRNAME[[:space:]]" > /dev/null || $EXSC -dm -S $SRNAME
   sleep 2 # needed for slow screen startup
   $EXSC -S "$SRNAME" -X screen nice $EXEC $OPTIONS
   for I in $(seq 0 5) ; do
     if [ -s ${SESSION}/rtorrent.lock ] ; then
       LFC="$(cat ${SESSION}/rtorrent.lock)" && PID=${LFC##*+}
       logger -t $NAME "Started PID: ${PID}"
       echo -e "\033[1;32mrtorrent started pid=${PID}\033[0m"
       break
     fi
     sleep 1
   done
   $EXSC -S $SRNAME -p sh -X eval 'stuff "^D"\015'
}

d_stop() {
  fwclose
  SESSION=$(getsession "$CONFIG")
  if ! [ -s ${SESSION}/rtorrent.lock ] ; then
    logger -t $NAME "Lock file failed: ${SESSION}/rtorrent.lock"
    echo -e "\033[1;33mMissing ${SESSION}/rtorrent.lock, what to stop?\033[0m"
    return
  fi
  LFC="$(cat ${SESSION}/rtorrent.lock)" && PID=${LFC##*+}
  if $EXPS -A | grep -sq $PID.*rtorrent ; then # pid belongs to rtorrent?
    kill -s INT "$PID"
    logger -t $NAME "Stopped PID: $PID"
    sleep 1
    for I in $(seq 0 5) ; do
      PIDK="$($EXPS -o pid ax | $EXSD -n '/'$PID'/p')"
      [ -z "$PIDK" ] && break
      sleep 2
    done
  fi
  SCSTOP=$($EXSC -list | $EXSD -n "s/[^0-9]*\([0-9]*\)\.$SRNAME.*/\1/p")
  if [ -n "$SCSTOP" ]; then # screen also terminates with last ps
    kill "$SCSTOP"
    logger -t $NAME "Stopped screen: $SCSTOP"
    echo -e "\033[1;33mStopped screen ($SCSTOP) as rtorrent did no exit properly.\033[0m"
    for I in $(seq 0 5) ; do
      PIDK="$($EXPS -o pid ax | $EXSD -n '/'$SCSTOP'/p')"
      [ -z "$PIDK" ] && break
      sleep 1
    done
  fi
}

checkcnfg

if [ -z "$1" ] ; then
    case $(echo "$0" | $EXSD 's:^.*/\(.*\):\1:g') in
        S??*) rc="start" ;;
        K??*) rc="stop" ;;
        *) rc="usage" ;;
    esac
else
    rc="$1"
fi

case "$rc" in
  start)
	echo "Starting $NAME"
	d_start
	echo "."
	;;
  stop)
	echo "Stopping $NAME"
	d_stop
	echo "."
	;;
  restart|force-reload)
	echo "Restarting $NAME"
	d_stop
	sleep 1
	d_start
	echo "."
	;;
  *)
	echo "Usage: $0 {start|stop|restart|force-reload}" >&2
	exit 1
	;;
esac

exit 0 