#!/usr/bin/env sh

# Root check
if [ "$(id -u)" -ne 0 ]; then
  echo "This script must be run as root." >&2
  exit 1
fi

SSLOCAL_PID_FILE="/opt/ss-tun/sslocal.pid"

config() {
  key="$1"
  echo "$SHADOWSOCKS_CONFIG" | jq -r ".$key"
}

prepare() {

  mkdir -p $(dirname "$SSLOCAL_PID_FILE")

  # Create tuntap device (leave as-is if present)
  ip tuntap add name "$(config tun_interface_name)" mode tun 2>/dev/null || true
}

disconnect() {
  test -f "$SSLOCAL_PID_FILE" && {
    kill -INT $(cat "$SSLOCAL_PID_FILE")
    rm "$SSLOCAL_PID_FILE"
  }

}

connect() {

  prepare

  sslocal \
    -s "$(config server):$(config server_port)" \
    -k "$(config password)" \
    -m "$(config method)" \
    -U \
    --protocol tun \
    --tcp-fast-open \
    -6 \
    --tun-interface-name "$(config tun_interface_name)" \
    --tun-interface-address "$(config tun_interface_address)" \
    --outbound-bind-interface "$OUTBOUND_BIND_INTERFACE" \
    --daemonize \
    --daemonize-pid "$SSLOCAL_PID_FILE"
}

# POSIX argument parsing
case "$1" in
-c)
  # Connect requires 2 additional arguments
  if [ $# -ne 3 ]; then
    echo "Error: -c requires a config path and a bind interface." >&2
    exit 1
  fi

  SHADOWSOCKS_CONFIG_PATH="$2"
  OUTBOUND_BIND_INTERFACE="$3"

  if [ ! -r "$SHADOWSOCKS_CONFIG_PATH" ] || [ -z "$OUTBOUND_BIND_INTERFACE" ]; then
    echo "Error: Config file not found or not readable at '$SHADOWSOCKS_CONFIG_PATH'" >&2
    exit 1
  fi

  SHADOWSOCKS_CONFIG="$(cat "$SHADOWSOCKS_CONFIG_PATH")"

  disconnect
  connect
  ;;
-d)
  disconnect
  exit 0
  ;;
*)
  echo "Error: Unknown option" >&2
  exit 1
  ;;
esac
