#!/usr/bin/env bash
# Exercise 2: make sense of ss, dig and curl output (medium)
# Run with: bash linux_networking_tools_exercise_2.sh
#
# Offline: every function reads canned command output from stdin.
#
# STEP 1: state_counts    — from `ss -tan` output print "STATE COUNT" sorted by
#                           count descending (ties: alphabetical by state)
# STEP 2: listening_ports — from `ss -tlnp` output print "PORT PROCESS" for each
#                           listener, sorted by port number; PROCESS is the name
#                           inside users:(("NAME",...)); mark listeners bound to
#                           loopback only with " (local)"
# STEP 3: close_wait_peers — from `ss -tan` print the remote IPs (without port)
#                            that have CLOSE-WAIT connections, with counts,
#                            "COUNT IP", biggest first
# STEP 4: min_ttl          — from `dig +noall +answer` output print the smallest TTL
# STEP 5: slowest_phase    — from a curl -w line
#           "dns=0.012 connect=0.045 tls=0.310 ttfb=0.920 total=0.950"
#         print the name of the phase that took the longest, where phase durations
#         are differences: dns, connect-dns (tcp), tls-connect (tls),
#         ttfb-tls (server), total-ttfb (transfer). Print one of:
#         dns, tcp, tls, server, transfer

set -uo pipefail

state_counts() {
  # TODO
  :
}

listening_ports() {
  # TODO
  :
}

close_wait_peers() {
  # TODO
  :
}

min_ttl() {
  # TODO
  :
}

slowest_phase() {
  # TODO: awk is handy for floating point
  :
}

# --- self-check: do not modify below this line ---
SS_TAN='State      Recv-Q Send-Q Local Address:Port   Peer Address:Port
LISTEN     0      511    0.0.0.0:80             0.0.0.0:*
LISTEN     0      200    127.0.0.1:5432         0.0.0.0:*
ESTAB      0      0      10.0.1.15:80           203.0.113.5:51200
ESTAB      0      0      10.0.1.15:80           203.0.113.9:40110
ESTAB      0      0      10.0.1.15:44120        10.0.2.30:5432
CLOSE-WAIT 1      0      10.0.1.15:39000        10.0.3.7:6379
CLOSE-WAIT 1      0      10.0.1.15:39002        10.0.3.7:6379
CLOSE-WAIT 1      0      10.0.1.15:39004        10.0.3.7:6379
CLOSE-WAIT 1      0      10.0.1.15:41000        10.0.4.2:443
TIME-WAIT  0      0      10.0.1.15:80           203.0.113.5:51188
TIME-WAIT  0      0      10.0.1.15:80           203.0.113.7:51190
TIME-WAIT  0      0      10.0.1.15:80           203.0.113.8:51191'

SS_TLNP='State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 0      511    0.0.0.0:80          0.0.0.0:*         users:(("nginx",pid=812,fd=6))
LISTEN 0      4096   127.0.0.1:5432      0.0.0.0:*         users:(("postgres",pid=640,fd=5))
LISTEN 0      128    0.0.0.0:22          0.0.0.0:*         users:(("sshd",pid=501,fd=3))
LISTEN 0      511    127.0.0.1:8080      0.0.0.0:*         users:(("node",pid=900,fd=21))'

DIG='api.petpal.io.     300  IN CNAME petpal-alb-123.eu-west-1.elb.amazonaws.com.
petpal-alb-123.eu-west-1.elb.amazonaws.com. 60 IN A 52.18.10.1
petpal-alb-123.eu-west-1.elb.amazonaws.com. 60 IN A 52.18.10.2'

all_ok=true
check() {
  if [[ "$2" == "$3" ]]; then echo "ok   $1"; else echo "FAIL $1"; echo "     got:      $(printf '%s' "$2" | tr '\n' '|')"; echo "     expected: $(printf '%s' "$3" | tr '\n' '|')"; all_ok=false; fi
}

check "state_counts" "$(printf '%s\n' "$SS_TAN" | state_counts)" "$(printf 'CLOSE-WAIT 4\nESTAB 3\nTIME-WAIT 3\nLISTEN 2')"
check "listening_ports" "$(printf '%s\n' "$SS_TLNP" | listening_ports)" "$(printf '22 sshd\n80 nginx\n5432 postgres (local)\n8080 node (local)')"
check "close_wait_peers" "$(printf '%s\n' "$SS_TAN" | close_wait_peers)" "$(printf '3 10.0.3.7\n1 10.0.4.2')"
check "min_ttl" "$(printf '%s\n' "$DIG" | min_ttl)" "60"
check "slowest_phase server" "$(echo 'dns=0.012 connect=0.045 tls=0.310 ttfb=0.920 total=0.950' | slowest_phase)" "server"
check "slowest_phase tls"    "$(echo 'dns=0.010 connect=0.030 tls=0.900 ttfb=1.000 total=1.050' | slowest_phase)" "tls"
check "slowest_phase dns"    "$(echo 'dns=2.000 connect=2.020 tls=2.100 ttfb=2.300 total=2.310' | slowest_phase)" "dns"
check "slowest_phase transfer" "$(echo 'dns=0.001 connect=0.010 tls=0.050 ttfb=0.100 total=3.000' | slowest_phase)" "transfer"

if $all_ok; then echo "PASS"; else echo "FAIL"; fi
