# ui::_render_endpoint_col # Builds padded endpoint string: "raw_ip → resolved" or "raw_ip" or "-" # Args: endpoint resolved w_endpoint # Returns: padded colored string via stdout function ui::_render_endpoint_col() { local endpoint="${1:-}" resolved="${2:-}" w_endpoint="${3:-20}" local colored visible_len pad_n if [[ -n "$endpoint" ]]; then if [[ -n "$resolved" ]]; then colored="${endpoint} \033[2m→ ${resolved}\033[0m" visible_len=$(( ${#endpoint} + 3 + ${#resolved} )) else colored="$endpoint" visible_len=${#endpoint} fi else colored="\033[2m—\033[0m" visible_len=1 fi pad_n=$(( w_endpoint - visible_len )) [[ $pad_n -lt 0 ]] && pad_n=0 printf "%b%*s" "$colored" "$pad_n" "" } # ui::_render_dest_col # Builds padded destination string: "svc/proto (ip:port)" or raw # Args: dest_ip dest_port proto svc_name w_dest resolved_only # Returns: two vars via nameref — dest_colored dest_pad_n function ui::_build_dest() { local dest_ip="${1:-}" dest_port="${2:-}" proto="${3:-}" \ svc_name="${4:-}" w_dest="${5:-20}" resolved_only="${6:-false}" local svc_display raw_suffix="" raw_plain="" if [[ -n "$svc_name" ]]; then [[ -n "$dest_port" ]] && svc_display="${svc_name}/${proto}" \ || svc_display="${svc_name} (${proto})" if ! $resolved_only; then [[ -n "$dest_port" ]] && raw_suffix=" \033[2m(${dest_ip}:${dest_port})\033[0m" \ || raw_suffix=" \033[2m(${dest_ip})\033[0m" [[ -n "$dest_port" ]] && raw_plain=" (${dest_ip}:${dest_port})" \ || raw_plain=" (${dest_ip})" fi else [[ -n "$dest_port" ]] && svc_display="${dest_ip}:${dest_port}/${proto}" \ || svc_display="${dest_ip} (${proto})" fi local full_len=$(( ${#svc_display} + ${#raw_plain} )) local dest_pad_n=$(( w_dest - full_len )) [[ $dest_pad_n -lt 0 ]] && dest_pad_n=0 # Output: svc_display|raw_suffix|dest_pad_n printf "%s\t%s\t%s" "$svc_display" "$raw_suffix" "$dest_pad_n" } function ui::watch::fw_row() { local ts="${1:-}" client="${2:-}" dest_ip="${3:-}" dest_port="${4:-}" \ proto="${5:-}" svc_name="${6:-}" \ src_endpoint="${7:-}" src_resolved="${8:-}" \ w_client="${9:-20}" w_dest="${10:-18}" w_endpoint="${11:-0}" local ts_pad client_pad ts_pad=$(printf "%-11s" "$ts") client_pad=$(printf "%-${w_client}s" "$client") local dest_parts dest_parts=$(ui::_build_dest "$dest_ip" "$dest_port" "$proto" "$svc_name" "$w_dest" "false") local svc_display raw_suffix dest_pad_n IFS=$'\t' read -r svc_display raw_suffix dest_pad_n <<< "$dest_parts" if [[ "$w_endpoint" -gt 0 ]]; then local src_padded src_padded=$(ui::_render_endpoint_col "$src_endpoint" "$src_resolved" "$w_endpoint") printf " %s %s %s \033[1;31m→\033[0m %s%b%*s \033[1;31mdrop\033[0m\n" \ "$ts_pad" "$client_pad" "$src_padded" \ "$svc_display" "$raw_suffix" "$dest_pad_n" "" else printf " %s %s \033[1;31m→\033[0m %s%b%*s \033[1;31mdrop\033[0m\n" \ "$ts_pad" "$client_pad" \ "$svc_display" "$raw_suffix" "$dest_pad_n" "" fi } function ui::watch::wg_row() { local ts="${1:-}" client="${2:-}" endpoint="${3:-}" event="${4:-}" \ src_resolved="${5:-}" \ w_client="${6:-20}" w_endpoint="${7:-18}" local event_color case "$event" in handshake) event_color="\033[1;32m" ;; attempt) event_color="\033[1;31m" ;; *) event_color="\033[0;37m" ;; esac local ep_padded ep_padded=$(ui::_render_endpoint_col "$endpoint" "$src_resolved" "$w_endpoint") local ts_pad client_pad ts_pad=$(printf "%-11s" "$ts") client_pad=$(printf "%-${w_client}s" "$client") printf " %s %s %s %b%s\033[0m\n" \ "$ts_pad" "$client_pad" "$ep_padded" \ "$event_color" "$event" }