Utoljára aktív 1 month ago

Revízió 5fe008dfad38ad80ff1858d906ffad1f0494dea1

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