#!/bin/bash

############################################################################################
# Author : dgrotti@sipwise.com
#
# Script will take the full list from redis DB 4 of callIDs, and check inside current
# kamailio.log if the dialogs for that calls were created (start) and destroyed (end/failed).
# It reports all the possibilities:
#
# * [END] = CallID with dialog 'start' + 'end' or 'failed'
# * [IN CALL] = CallID with dialog 'start' AND NO 'end' or 'failed' AND NO BYE
# * [ERROR] = CallID with dialog 'start' + AND NOT 'end' or 'failed' WITH BYE
# * [RINGING] = Callid still ringing
# * [NOT FOUND] = CallID was not found in current log
#
#
#
# In case of ERROR or NOT FOUND it means that the CallID was not removed from Redis DB 4 for some reasons
# and then the counters was not probably decrease. So such callids needs to be investigated.
#
###############################################################################################

set -e

# --- colors vars ---
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m' # No Color

# ---- general vars ---
NGCP_HOSTNAME=$(ngcp-hostname)
ME="$0"
DATE=$(date)
PROXY_LOG="/var/log/ngcp/kamailio-proxy.log"
FILE=$(mktemp -t ngcp-check-redis-dialogs-file.XXXXXXXXXX)

# --- exit handling -----
bailout() {
  [ -n "${1:-}" ] && EXITCODE="$1" || EXITCODE=1
  rm -f "${FILE:-}"
  exit "$EXITCODE"
}
trap bailout SIGHUP SIGINT SIGQUIT SIGABRT SIGALRM SIGTERM

# --- help -----
function usage {
	echo "$ME - script to check id callIDs in redis DB 4 are well destroyed"
	echo "Usage: $ME"
	bailout 0
}

get_configs() {
  if [ -f /usr/share/ngcp-ngcpcfg/scripts/values ] ; then
    pair="$(ngcpcfg get redis.db.kamailio.proxy.dlgcnt_pair)"
  else
    pair=4
  fi

  # note: we're using only on the *last* bind configuration directive,
  # even if multiple might be configured (e.g. for `bind 127.0.0.1 ::1`
  # we will use `::1` as $host)
  if [ -r /etc/keydb/keydb.conf ] ; then
    host=$(awk '/^bind/ {print $NF}' /etc/keydb/keydb.conf)
  elif [ -r /etc/redis/redis.conf ] ; then
    host=$(awk '/^bind/ {print $NF}' /etc/redis/redis.conf)
  else
    echo "Error: couldn't read /etc/keydb/keydb.conf nor /etc/redis/redis.conf, giving up." >&2
    exit 1
  fi
}

function check_own_dependencies {
	if ! [ -r /etc/default/ngcp-roles ] ; then
		echo "Warning: cannot read /etc/default/ngcp-roles, continue anyway" >&2
	else
		# shellcheck disable=SC1091
		source /etc/default/ngcp-roles
	fi
}

function fetch_callids {
	if ngcp-check-active -q && \
           { [ "$NGCP_TYPE" = "sppro" ] || [ "$NGCP_IS_PROXY" = "yes" ]; }
	then
		get_configs
		ngcp-redis-helper -h "$host" -n "$pair" dumps | grep -vE '^list:' > "$FILE" || true
	else
		echo "Please run the script on ACTIVE proxy, not in ${NGCP_HOSTNAME}." >&2
		bailout 1
	fi
}

case "$1" in
	-h|--help) usage ;;
esac
check_own_dependencies
fetch_callids

# --- counters ----
TOTAL_CALLIDS=$(wc -l < "$FILE")
NOT_FOUND=0
END=0
IN_CALL=0
ERROR=0
RINGING=0
GREP_CALLID=$(mktemp -t ngcp-check-redis-dialogs-callid.XXXXXXXXXX)

while read -r i ; do
	if [[ "$i" == '[' || "$i" == ']' || "$i" == "Database is empty" ]]; then
		continue
	fi
	# grep all info related to callid $i
	if ! grep -E "$i" $PROXY_LOG > "$GREP_CALLID" ; then
		((NOT_FOUND = NOT_FOUND + 1))
		echo -e "${RED}[NOT FOUND]${NC} CallID '$i' not found in today log"
		continue
	fi
	if grep -qE 'dialog:start' "$GREP_CALLID" ; then
		## if call has start, needs to have END or a FAILURE
		if grep -qE 'dialog:end|dialog:failed' "$GREP_CALLID" ; then
			echo "[END] CallID '$i' is ended"
			((END = END + 1))
		else
			# if END or FAILED is not there, maybe the call is not closed yet? (no BYE)
			if grep -q 'BYE' "$GREP_CALLID" ; then
				echo -e "${RED}[ERROR]${NC} CallId '$i' has START but not END/FAILED"
				((ERROR = ERROR + 1))
			else
				echo -e "${GREEN}[IN CALL]${NC} CallID '$i' is still talking"
				((IN_CALL = IN_CALL + 1))
			fi
		fi
	else
		if grep -qE 'dialog:failed' "$GREP_CALLID" ; then
			echo "[END] CallID '$i' is ended"
			((END = END + 1))
		## call with INVITE but not dialog:start yet (RINGING?)
		elif grep -qE 'BYE|CANCEL' "$GREP_CALLID" ; then
			echo -e "${RED}[ERROR]${NC} CallId '$i' has NO START but Call in ended."
			((ERROR = ERROR + 1))
		elif grep -qE 'S=200' "$GREP_CALLID" ; then
			echo -e "${RED}[ERROR]${NC} CallId '$i' has NO START but Call is on."
			((ERROR = ERROR + 1))
		elif grep -qE "S=(100|180|183)" "$GREP_CALLID" ; then
			echo -e "${YELLOW}[RINGING]${NC} CallId '$i' is ringing"
			((RINGING = RINGING + 1))
		else
			echo "[?] $i has no ringing?"
		fi
	fi
done < "$FILE"

rm "$GREP_CALLID" "$FILE"

echo ""
echo "===== Results $DATE ======"

echo -e "Total CallIDs parsed: $TOTAL_CALLIDS"
echo -e "Not found:            ${RED}$NOT_FOUND${NC}"
echo -e "Ended Ok:             $END"
echo -e "In call:              ${GREEN}$IN_CALL${NC}"
echo -e "Ringing:              ${YELLOW}$RINGING${NC}"
echo -e "Error (no end):       ${RED}$ERROR${NC}"
echo ""
echo "[END] CallIDs should disappear in next execution"

ngcp-kamctl proxy fifo stats.get_statistics dialog: | grep "active\|early" | tr -d ', "'

bailout 0
