Son aktivite 1 month ago

gistfile1.txt Ham
1function cmd::activity::run() {
2 local filter_peer="" filter_service="" filter_ip="" filter_type=""
3 local hours=24 dropped_only=false
4 local accept_only=false drop_only=false external_only=false
5
6 while [[ $# -gt 0 ]]; do
7 case "$1" in
8 --peer) filter_peer="$2"; shift 2 ;;
9 --service) filter_service="$2"; shift 2 ;;
10 --ip) filter_ip="$2"; shift 2 ;;
11 --type) filter_type="$2"; shift 2 ;;
12 --hours) hours="$2"; shift 2 ;;
13 --dropped) dropped_only=true; shift ;;
14 --accept) accept_only=true; shift ;;
15 --drop) drop_only=true; shift ;;
16 --external) external_only=true; shift ;;
17 --help) cmd::activity::help; return ;;
18 *)
19 log::error "Unknown flag: $1"
20 cmd::activity::help
21 return 1
22 ;;
23 esac
24 done
25
26 if command::json; then
27 cmd::activity::_output_json "$hours"
28 return 0
29 fi
30
31 # Resolve peer name if type provided
32 if [[ -n "$filter_peer" && -n "$filter_type" ]]; then
33 filter_peer=$(peers::resolve_and_require "$filter_peer" "$filter_type") || return 1
34 fi
35
36 # Resolve --service to IP
37 local service_ip=""
38 if [[ -n "$filter_service" ]]; then
39 service_ip=$(net::resolve "$filter_service" 2>/dev/null | head -1 | cut -d: -f1) || true
40 if [[ -z "$service_ip" ]]; then
41 log::error "Service not found: ${filter_service}"
42 return 1
43 fi
44 fi
45 [[ -n "$filter_ip" ]] && service_ip="$filter_ip"
46
47 # Fetch drop/handshake data
48 local data=""
49 if ! $accept_only; then
50 data=$(json::activity_aggregate \
51 "$(ctx::fw_events_log)" \
52 "$(ctx::events_log)" \
53 "$(config::interface)" \
54 "$(ctx::net)" \
55 "$(ctx::clients)" \
56 "$(ctx::meta)" \
57 "$hours" \
58 "$filter_peer" \
59 "$service_ip" 2>/dev/null)
60 fi
61
62 # Fetch accept data
63 local accept_data=""
64 if ! $drop_only; then
65 local since_arg=""
66 [[ "$hours" -gt 0 ]] && since_arg="${hours}h"
67 local ext_flag="0"
68 $external_only && ext_flag="1"
69 [[ -f "$(ctx::accept_events_log)" ]] && \
70 accept_data=$(json::accept_aggregate \
71 "$(ctx::accept_events_log)" \
72 "$(ctx::net)" \
73 "$(ctx::clients)" \
74 "$since_arg" \
75 "$filter_peer" \
76 "$ext_flag" \
77 2>/dev/null)
78 fi
79
80 if [[ -z "$data" && -z "$accept_data" ]]; then
81 log::wg_warning "No activity data found"
82 return 0
83 fi
84
85 # Build accept lookup maps
86 declare -gA _ACCEPT_PEER=()
87 declare -gA _ACCEPT_DEST_KEYS=()
88 declare -gA _ACCEPT_DEST=()
89
90 while IFS='|' read -r type rest; do
91 [[ -z "$type" ]] && continue
92 case "$type" in
93 peer)
94 local a_name a_bi a_bo a_pi a_po a_conns
95 IFS='|' read -r a_name a_bi a_bo a_pi a_po a_conns <<< "$rest"
96 _ACCEPT_PEER["$a_name"]="${a_bi}|${a_bo}|${a_pi}|${a_po}|${a_conns}"
97 ;;
98 dest)
99 local d_peer d_ip d_port d_proto d_bytes d_count
100 IFS='|' read -r d_peer d_ip d_port d_proto d_bytes d_count <<< "$rest"
101 local d_key="${d_peer}:${d_ip}:${d_port}:${d_proto}"
102 _ACCEPT_DEST["$d_key"]="${d_bytes}|${d_count}"
103 _ACCEPT_DEST_KEYS["$d_peer"]+="${d_key} "
104 ;;
105 esac
106 done <<< "$accept_data"
107
108 # Measure column widths
109 local w_peer=16 w_drops=1
110 while IFS='|' read -r type rest; do
111 case "$type" in
112 peer)
113 local name drops
114 name=$(echo "$rest" | cut -d'|' -f1)
115 drops=$(echo "$rest" | cut -d'|' -f4)
116 (( ${#name} > w_peer )) && w_peer=${#name}
117 (( ${#drops} > w_drops )) && w_drops=${#drops}
118 ;;
119 service)
120 local count
121 count=$(echo "$rest" | cut -d'|' -f3)
122 (( ${#count} > w_drops )) && w_drops=${#count}
123 ;;
124 esac
125 done <<< "$data"
126
127 for a_name in "${!_ACCEPT_PEER[@]}"; do
128 (( ${#a_name} > w_peer )) && w_peer=${#a_name}
129 done
130
131 (( w_peer += 2 ))
132 local drops_col=$(( w_peer + 30 ))
133
134 local hours_display="${hours}h"
135 [[ "$hours" == "0" ]] && hours_display="all time"
136
137 log::section "Activity Monitor (last ${hours_display})"
138 echo ""
139
140 if display::is_table "activity"; then
141 cmd::activity::_render_table "$data"
142 return 0
143 fi
144
145 # Helper — render accept dests for a peer inline
146 _render_peer_accept_dests() {
147 local peer_name="$1"
148 local keys="${_ACCEPT_DEST_KEYS[$peer_name]:-}"
149 [[ -z "$keys" ]] && return 0
150 for d_key in $keys; do
151 local dest_stats="${_ACCEPT_DEST[$d_key]:-}"
152 [[ -z "$dest_stats" ]] && continue
153 local d_bytes d_count
154 IFS='|' read -r d_bytes d_count <<< "$dest_stats"
155 local rest_key="${d_key#${peer_name}:}"
156 local d_ip d_port d_proto
157 d_ip="${rest_key%%:*}"
158 local pp="${rest_key#*:}"
159 d_port="${pp%%:*}"
160 d_proto="${pp##*:}"
161 local dest_display
162 dest_display=$(resolve::dest "$d_ip" "$d_port" "$d_proto" 2>/dev/null \
163 || echo "${d_ip}:${d_port}/${d_proto}")
164 local bytes_fmt
165 bytes_fmt=$(fmt::bytes "$d_bytes")
166 ui::activity::accept_dest_row \
167 "$dest_display" "$d_bytes" "$bytes_fmt" \
168 "$d_count" "$drops_col" "$w_drops"
169 done
170 }
171
172 local first_peer=true skip_peer=false current_name=""
173 local -a rendered_peers=()
174
175 while IFS='|' read -r record_type rest; do
176 case "$record_type" in
177 peer)
178 local name rx tx drops
179 IFS='|' read -r name rx tx drops <<< "$rest"
180
181 # Flush previous peer's accept dests before starting new peer
182 if [[ -n "$current_name" ]] && ! $drop_only; then
183 _render_peer_accept_dests "$current_name"
184 fi
185
186 skip_peer=false
187 current_name="$name"
188 local has_accept="${_ACCEPT_PEER[$name]:-}"
189
190 if $dropped_only && [[ "$drops" -eq 0 ]] && [[ -z "$has_accept" ]]; then
191 skip_peer=true
192 continue
193 fi
194
195 $first_peer || echo ""
196 first_peer=false
197 rendered_peers+=("$name")
198
199 local rx_fmt tx_fmt
200 rx_fmt=$(fmt::bytes "$rx")
201 tx_fmt=$(fmt::bytes "$tx")
202
203 local name_pad rx_pad tx_pad
204 name_pad=$(printf "%-${w_peer}s" "$name")
205 rx_pad=$(printf "%-10s" "$rx_fmt")
206 tx_pad=$(printf "%-10s" "$tx_fmt")
207
208 local drop_word="drops"
209 [[ "$drops" -eq 1 ]] && drop_word="drop"
210
211 if ! $accept_only; then
212 ui::activity::peer_row \
213 "$name_pad" "$rx_pad" "$tx_pad" "$drops" "$drop_word" "$w_drops"
214 fi
215
216 # Accept summary row
217 if [[ -n "$has_accept" ]] && ! $drop_only; then
218 local a_bi a_bo a_pi a_po a_conns
219 IFS='|' read -r a_bi a_bo a_pi a_po a_conns <<< "$has_accept"
220 local a_in_fmt a_out_fmt
221 a_in_fmt=$(fmt::bytes "$a_bi")
222 a_out_fmt=$(fmt::bytes "$a_bo")
223 ui::activity::accept_row \
224 "$name_pad" "$a_in_fmt" "$a_out_fmt" "$a_conns" "$w_drops"
225 fi
226 ;;
227
228 service)
229 $skip_peer && continue
230 local peer dest_display drop_count
231 IFS='|' read -r peer dest_display drop_count <<< "$rest"
232 local svc_drop_word="drops"
233 [[ "$drop_count" -eq 1 ]] && svc_drop_word="drop"
234 if ! $accept_only; then
235 ui::activity::service_row \
236 "$dest_display" "$drop_count" "$svc_drop_word" "$drops_col" "$w_drops"
237 fi
238 ;;
239 esac
240 done <<< "$data"
241
242 # Flush last peer's accept dests
243 if [[ -n "$current_name" ]] && ! $drop_only; then
244 _render_peer_accept_dests "$current_name"
245 fi
246
247 # Accept-only peers — not in drop data, render separately
248 if ! $drop_only; then
249 for a_name in $(echo "${!_ACCEPT_PEER[@]}" | tr ' ' '\n' | sort); do
250 local already=false
251 for rp in "${rendered_peers[@]:-}"; do
252 [[ "$rp" == "$a_name" ]] && already=true && break
253 done
254 $already && continue
255
256 $first_peer || echo ""
257 first_peer=false
258
259 local a_stats="${_ACCEPT_PEER[$a_name]}"
260 local a_bi a_bo a_pi a_po a_conns
261 IFS='|' read -r a_bi a_bo a_pi a_po a_conns <<< "$a_stats"
262 local a_in_fmt a_out_fmt
263 a_in_fmt=$(fmt::bytes "$a_bi")
264 a_out_fmt=$(fmt::bytes "$a_bo")
265 local name_pad
266 name_pad=$(printf "%-${w_peer}s" "$a_name")
267local a_in_pad a_out_pad
268a_in_pad=$(printf "%-10s" "$a_in_fmt")
269a_out_pad=$(printf "%-10s" "$a_out_fmt")
270ui::activity::accept_row \
271 "$name_pad" "$a_in_pad" "$a_out_pad" "$a_conns" "$w_drops"
272 done
273 fi
274
275 echo ""
276}