1 |
#!/usr/bin/perl |
2 |
|
3 |
# NetMonitor |
4 |
|
5 |
# Copyright (C) 1999-2006 Mandriva |
6 |
# Damien "Dam's" Krotkine |
7 |
# Thierry Vignaud <tvignaud@mandriva.com> |
8 |
# |
9 |
# This program is free software; you can redistribute it and/or modify |
10 |
# it under the terms of the GNU General Public License as published by |
11 |
# the Free Software Foundation; either version 2, or (at your option) |
12 |
# any later version. |
13 |
# |
14 |
# This program is distributed in the hope that it will be useful, |
15 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 |
# GNU General Public License for more details. |
18 |
# |
19 |
# You should have received a copy of the GNU General Public License |
20 |
# along with this program; if not, write to the Free Software |
21 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 |
|
23 |
use lib qw(/usr/lib/libDrakX); |
24 |
|
25 |
use strict; |
26 |
# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) |
27 |
BEGIN { unshift @::textdomains, 'drakx-net' } |
28 |
use standalone; #- warning, standalone must be loaded very first, for 'explanations' |
29 |
|
30 |
use c; |
31 |
use interactive; |
32 |
use mygtk2 qw(gtknew gtkset); |
33 |
use ugtk2 qw(:create :helpers :wrappers); |
34 |
use common; |
35 |
use network::network; |
36 |
use network::tools; |
37 |
use POSIX; |
38 |
|
39 |
$ugtk2::wm_icon = "/usr/share/mcc/themes/default/net_monitor-mdk.png"; |
40 |
|
41 |
if ("@ARGV" =~ /--status/) { print network::tools::connected(); exit(0) } |
42 |
my $force = "@ARGV" =~ /--force/; |
43 |
my $quiet = "@ARGV" =~ /--quiet/; |
44 |
my $connect = "@ARGV" =~ /--connect/; |
45 |
my $disconnect = "@ARGV" =~ /--disconnect/; |
46 |
my ($default_intf) = "@ARGV" =~ /--defaultintf (\w+)/; |
47 |
|
48 |
my $net = {}; |
49 |
network::network::read_net_conf($net); |
50 |
$default_intf ||= $net->{net_interface}; |
51 |
|
52 |
if ($force) { |
53 |
$connect and network::tools::start_interface($default_intf, 1); |
54 |
$disconnect and network::tools::stop_interface($default_intf, 1); |
55 |
$connect = $disconnect = 0; |
56 |
} |
57 |
$quiet and exit(0); |
58 |
|
59 |
|
60 |
my $window1 = ugtk2->new(N("Network Monitoring")); |
61 |
$window1->{window}->signal_connect(delete_event => \&main_quit); |
62 |
|
63 |
unless ($::isEmbedded) { |
64 |
$window1->{window}->set_position('center'); |
65 |
$window1->{window}->set_title(N("Network Monitoring")); |
66 |
$window1->{window}->set_border_width(5); |
67 |
} |
68 |
#$::isEmbedded or $window1->{window}->set_size_request(580, 320); |
69 |
|
70 |
my $colorr = gtkcolor(50400, 655, 20000); |
71 |
my $colort = gtkcolor(55400, 55400, 655); |
72 |
my $colora = gtkcolor(655, 50400, 655); |
73 |
my $isconnected = -1; |
74 |
my @interfaces; |
75 |
my $monitor = {}; |
76 |
my $c_time = 0; |
77 |
my $ct_tag; |
78 |
|
79 |
my ($pixmap, $darea, $gc_lines); |
80 |
my ($width, $height) = (300, 150); |
81 |
|
82 |
my $left_border = 50; |
83 |
my $grid_interval = 30; |
84 |
my $arrow_space = 6; |
85 |
my $arrow_size = 5; |
86 |
|
87 |
my $cfg_file = $< ? "$ENV{HOME}/.net_monitorrc" : "/etc/sysconfig/net_monitorrc"; |
88 |
my %config = getVarsFromSh($cfg_file); |
89 |
my $use_same_scale = text2bool($config{use_same_scale}); |
90 |
|
91 |
gtkadd($window1->{window}, |
92 |
gtknew('VBox', spacing => 5, children => [ |
93 |
1, gtknew('HBox', spacing => 5, children => [ |
94 |
0, my $notebook = gtknew('Notebook'), |
95 |
1, gtknew('VBox', spacing => 5, children => [ |
96 |
0, gtknew('Frame', text => N("Settings"), shadow_type => 'etched_out', child => |
97 |
gtknew('VBox', border_width => 5, children_tight => [ |
98 |
gtknew('HBox', border_width => 5, children_tight => [ |
99 |
N("Default connection: "), |
100 |
my $label_cnx_type = gtknew('Label', text => "") ]), |
101 |
my $button_connect = gtknew('Button', text => N("Wait please"), sensitive => 0, clicked => \&connection), |
102 |
]), |
103 |
), |
104 |
1, gtknew('Frame', text => N("Global statistics"), shadow_type => 'etched_out', child => |
105 |
gtknew('VBox', border_width => 5, children_tight => [ |
106 |
gtknew('Table', col_spacings => 1, row_spacings => 5, homogeneous => 1, children => [ |
107 |
[ gtknew('Label', text => ""), gtknew('Label', text => N("Instantaneous")) , gtknew('Label', text => N("Average")) ], |
108 |
[ gtknew('WrappedLabel', text => N("Sending\nspeed:")), my $label_st = gtknew('Label', text => ""), my $label_sta = gtknew('Label', text => N("unknown")) ], |
109 |
[ gtknew('WrappedLabel', text => N("Receiving\nspeed:")), my $label_sr = gtknew('Label', text => ""), my $label_sra = gtknew('Label', text => N("unknown")) ], |
110 |
]), |
111 |
gtknew('HSeparator'), |
112 |
gtknew('HBox', border_width => 5, children_loose => [ |
113 |
N("Connection time: "), |
114 |
my $label_ct = gtknew('Label', text => N("unknown")), |
115 |
]), |
116 |
]) |
117 |
), |
118 |
]) |
119 |
]), |
120 |
0, gtksignal_connect(gtkset_active(gtknew('CheckButton', text => N("Use same scale for received and transmitted")), $use_same_scale), clicked => sub { $use_same_scale = !$use_same_scale }), |
121 |
0, gtknew('HButtonBox', layout => 'edge', children_loose => [ |
122 |
my $button_close = gtknew('Button', text => N("Close"), clicked => \&main_quit), |
123 |
]), |
124 |
0, my $statusbar = Gtk2::Statusbar->new |
125 |
]), |
126 |
); |
127 |
|
128 |
$window1->{window}->show_all; |
129 |
$window1->{window}->realize; |
130 |
|
131 |
my $gct = Gtk2::Gdk::GC->new($window1->{window}->window); |
132 |
$gct->set_foreground($colort); |
133 |
my $gcr = Gtk2::Gdk::GC->new($window1->{window}->window); |
134 |
$gcr->set_foreground($colorr); |
135 |
my $gca = Gtk2::Gdk::GC->new($window1->{window}->window); |
136 |
$gca->set_foreground($colora); |
137 |
|
138 |
$statusbar->push(1, N("Wait please, testing your connection...")); |
139 |
$window1->{window}->show_all; |
140 |
|
141 |
# make sure widgets got realized before any event callback is called (#36537): |
142 |
gtkflush(); |
143 |
|
144 |
my $time_tag1 = Glib::Timeout->add(1000, \&rescan); |
145 |
my $time_tag2 = Glib::Timeout->add(1000, \&update); |
146 |
|
147 |
update(); |
148 |
rescan(); |
149 |
|
150 |
gtkflush() while $isconnected == -2 || $isconnected == -1; |
151 |
|
152 |
Glib::Source->remove($time_tag2); |
153 |
$time_tag2 = Glib::Timeout->add(5000, \&update); |
154 |
|
155 |
connection() if $connect && !$isconnected || $disconnect && $isconnected; |
156 |
|
157 |
my $tool_pid; |
158 |
|
159 |
$SIG{CHLD} = sub { |
160 |
my $child_pid; |
161 |
do { |
162 |
$child_pid = waitpid(-1, POSIX::WNOHANG); |
163 |
if ($tool_pid eq $child_pid) { |
164 |
undef $tool_pid; |
165 |
$button_close->set_sensitive(1); |
166 |
} |
167 |
} while $child_pid > 0; |
168 |
}; |
169 |
|
170 |
|
171 |
$window1->main; |
172 |
main_quit(); |
173 |
|
174 |
my $during_connection; |
175 |
my $first; |
176 |
|
177 |
sub main_quit() { |
178 |
foreach my $timeout ($time_tag1, $time_tag2) { |
179 |
Glib::Source->remove($timeout) if $timeout; |
180 |
} |
181 |
$config{use_same_scale} = bool2yesno($use_same_scale); |
182 |
setVarsInSh($cfg_file, \%config); |
183 |
ugtk2->exit(0); |
184 |
} |
185 |
|
186 |
sub getcurrentintf() { |
187 |
my $currp = $notebook->get_current_page; |
188 |
foreach (@interfaces) { |
189 |
my $intf = $_; |
190 |
return $intf if $monitor->{$intf}{page} == $currp; |
191 |
} |
192 |
} |
193 |
|
194 |
sub intf_reset() { |
195 |
# resets counters for currently selected tab |
196 |
my $intf = getcurrentintf(); |
197 |
if (defined $intf) { |
198 |
$monitor->{$intf}{totalt} = 0; |
199 |
$monitor->{$intf}{totalr} = 0; |
200 |
} |
201 |
} |
202 |
|
203 |
sub connection() { |
204 |
$during_connection = 1; |
205 |
my $wasconnected = $isconnected; |
206 |
|
207 |
$button_connect->set_sensitive(0); |
208 |
$button_close->set_sensitive(0); |
209 |
$statusbar->pop(1); |
210 |
$statusbar->push(1, $wasconnected ? N("Disconnecting from Internet ") : N("Connecting to Internet ")); |
211 |
if ($wasconnected == 0) { |
212 |
$c_time = time(); |
213 |
$ct_tag = Glib::Timeout->add(1000, sub { |
214 |
my ($sec, $min, $hour) = gmtime(time() - $c_time); |
215 |
my $e = sprintf("%02d:%02d:%02d", $hour, $min, $sec); |
216 |
gtkset($label_ct, text => $e); 1 }); |
217 |
} |
218 |
my $nb_point = 1; |
219 |
$first = 1; |
220 |
|
221 |
my $_tag = Glib::Timeout->add(1000, sub { |
222 |
$statusbar->pop(1); |
223 |
$statusbar->push(1, ($wasconnected == 1 ? N("Disconnecting from Internet ") : N("Connecting to Internet ")) |
224 |
. join('', map { "." } (1..$nb_point))); |
225 |
$nb_point++; |
226 |
if ($nb_point < 4) { return 1 } |
227 |
my $ret = 1; |
228 |
|
229 |
my $isconnect = test_connected(0); |
230 |
|
231 |
if ($nb_point < 20) { |
232 |
if ($first == 1) { # first time |
233 |
if ($isconnect == -2) { # wait for last test to finish |
234 |
test_connected(2); # not yet terminated, try to cancel it |
235 |
return 1; |
236 |
} |
237 |
test_connected(1); # initiates new connection test |
238 |
$first = 0; |
239 |
return 1; |
240 |
} |
241 |
if ($isconnect == -2) { return 1 } # no result yet, wait. |
242 |
if ($isconnect == $wasconnected) { |
243 |
# we got a test result; but the connection state did not change; retry. |
244 |
test_connected(1); |
245 |
return 1; |
246 |
} |
247 |
} |
248 |
# either we got a result, or we timed out. |
249 |
if ($isconnect != -2 || $nb_point > 20) { |
250 |
$isconnected = $isconnect; |
251 |
$ret = 0; |
252 |
$statusbar->pop(1); |
253 |
$statusbar->push(1, $wasconnected ? ($isconnected ? |
254 |
N("Disconnection from Internet failed.") : |
255 |
N("Disconnection from Internet complete.")) : |
256 |
($isconnected ? |
257 |
N("Connection complete.") : |
258 |
N("Connection failed.\nVerify your configuration in the Mageia Linux Control Center.")) |
259 |
); |
260 |
# remove the connection time timer if connection is down or failed |
261 |
$isconnected or Glib::Source->remove($ct_tag); |
262 |
my $delay = 1000; |
263 |
# keep the message displayed longer if there is a problem. |
264 |
if ($isconnected == $wasconnected) { $delay = 5000 } |
265 |
my $_tag3 = Glib::Timeout->add($delay, sub { |
266 |
|
267 |
$button_connect->set_sensitive(1); |
268 |
$button_close->set_sensitive(1); |
269 |
undef $during_connection; |
270 |
update(); |
271 |
return 0; |
272 |
}); |
273 |
} |
274 |
return $ret; |
275 |
}); |
276 |
|
277 |
gtkflush(); |
278 |
|
279 |
print "Action on " . getcurrentintf() . "\n"; |
280 |
|
281 |
$tool_pid = |
282 |
$wasconnected == 1 |
283 |
? network::tools::stop_interface(getcurrentintf(), 1) |
284 |
: network::tools::start_interface(getcurrentintf(), 1); |
285 |
} |
286 |
|
287 |
sub graph_window_width() { $width - $left_border } |
288 |
|
289 |
sub rescan() { |
290 |
get_val(); |
291 |
foreach (@interfaces) { |
292 |
my $intf = $_; |
293 |
my $recv = $monitor->{$intf}{val}[0]; |
294 |
my $transmit = $monitor->{$intf}{val}[8]; |
295 |
my $refr = $monitor->{$intf}{referencer}; |
296 |
my $reft = $monitor->{$intf}{referencet}; |
297 |
my $diffr = $recv - $refr; |
298 |
my $difft = $transmit - $reft; |
299 |
|
300 |
# prevent for case 32 bits or 64 bits unsigned value of /proc (if rotate to zero) |
301 |
if ($diffr < 0) { |
302 |
if ($refr < 2**32) { # transition (2^32 - 1) to 0 |
303 |
$diffr += 2**32; |
304 |
} else { $diffr += 2**64 } # transition (2^64 - 1) to 0 |
305 |
# { $diffr = 0; $monitor->{$intf}{totalr} = 0 } # Alternatively, if bug for very big number in perl |
306 |
} |
307 |
# prevent for case 32 bits or 64 bits unsigned value of /proc (if rotate to zero) |
308 |
if ($difft < 0) { |
309 |
if ($reft < 2**32) { # transition (2^32 - 1) to 0 |
310 |
$difft += 2**32; |
311 |
} else { $difft += 2**64 } # transition (2^64 - 1) to 0 |
312 |
# { $difft = 0; $monitor->{$intf}{totalt} = 0 } # Alternatively, if bug for very big number in perl |
313 |
} |
314 |
|
315 |
$monitor->{$intf}{totalr} += $diffr; |
316 |
$monitor->{$intf}{totalt} += $difft; |
317 |
$monitor->{sr} += $diffr; |
318 |
$monitor->{st} += $difft; |
319 |
|
320 |
$monitor->{$intf}{recva} += $diffr; |
321 |
$monitor->{$intf}{recvan}++; |
322 |
if ($monitor->{$intf}{recvan} > 9) { |
323 |
push(@{$monitor->{$intf}{stack_ra}}, $monitor->{$intf}{recva}/10); |
324 |
$monitor->{$intf}{recva} = $monitor->{$intf}{recvan} = 0; |
325 |
} else { push(@{$monitor->{$intf}{stack_ra}}, -1) } |
326 |
shift @{$monitor->{$intf}{stack_ra}} if @{$monitor->{$intf}{stack_ra}} > graph_window_width(); |
327 |
|
328 |
push(@{$monitor->{$intf}{stack_r}}, $diffr); |
329 |
shift @{$monitor->{$intf}{stack_r}} if @{$monitor->{$intf}{stack_r}} > graph_window_width(); |
330 |
$monitor->{$intf}{labelr}->set_label(formatXiB($monitor->{$intf}{totalr})); |
331 |
$monitor->{$intf}{referencer} = $recv; |
332 |
|
333 |
$monitor->{$intf}{transmita} += $difft; |
334 |
$monitor->{$intf}{transmitan}++; |
335 |
if ($monitor->{$intf}{transmitan} > 9) { |
336 |
push(@{$monitor->{$intf}{stack_ta}}, $monitor->{$intf}{transmita}/10); |
337 |
$monitor->{$intf}{transmita} = $monitor->{$intf}{transmitan} = 0; |
338 |
} else { push(@{$monitor->{$intf}{stack_ta}}, -1) } |
339 |
shift @{$monitor->{$intf}{stack_ta}} if @{$monitor->{$intf}{stack_ta}} > graph_window_width(); |
340 |
|
341 |
push(@{$monitor->{$intf}{stack_t}}, $difft); |
342 |
shift @{$monitor->{$intf}{stack_t}} if @{$monitor->{$intf}{stack_t}} > graph_window_width(); |
343 |
$monitor->{$intf}{labelt}->set_label(formatXiB($monitor->{$intf}{totalt})); |
344 |
$monitor->{$intf}{referencet} = $transmit; |
345 |
|
346 |
draw_monitor($monitor->{$intf}, $intf); |
347 |
} |
348 |
gtkset($label_sr, text => formatXiB($monitor->{sr}) . "/s"); |
349 |
gtkset($label_st, text => formatXiB($monitor->{st}) . "/s"); |
350 |
$monitor->{sra} += $monitor->{sr}; |
351 |
$monitor->{sta} += $monitor->{st}; |
352 |
$monitor->{nba}++; |
353 |
if ($monitor->{nba} > 9) { |
354 |
gtkset($label_sra, text => formatXiB($monitor->{sra}/10) . "/s"); |
355 |
gtkset($label_sta, text => formatXiB($monitor->{sta}/10) . "/s"); |
356 |
$monitor->{sra} = 0; |
357 |
$monitor->{sta} = 0; |
358 |
$monitor->{nba} = 0; |
359 |
} |
360 |
gtkset($label_cnx_type, text => N("%s (%s)", translate($net->{type}), $net->{net_interface})); |
361 |
$monitor->{$_} = 0 foreach 'sr', 'st'; |
362 |
1; |
363 |
} |
364 |
|
365 |
sub get_val() { |
366 |
my $a = cat_("/proc/net/dev"); |
367 |
$a =~ s/^.*?\n.*?\n//; |
368 |
$a =~ s/^\s*lo:.*?\n//; |
369 |
my @line = split(/\n/, $a); |
370 |
require detect_devices; |
371 |
my @net_devices = detect_devices::get_net_interfaces(); |
372 |
map { |
373 |
s/\s*(\w*)://; |
374 |
my $intf = $1; |
375 |
if (member($intf, @net_devices)) { |
376 |
$monitor->{$intf}{val} = [ split() ]; |
377 |
$monitor->{$intf}{intf} = $intf; |
378 |
$intf; |
379 |
} else { () } |
380 |
} @line; |
381 |
} |
382 |
|
383 |
sub change_color { |
384 |
my ($color) = @_; |
385 |
my $dialog = _create_dialog(N("Color configuration")); |
386 |
$dialog->vbox->add(my $colorsel = Gtk2::ColorSelection->new); |
387 |
$colorsel->set_current_color($color); |
388 |
$dialog->add_button(N("Cancel"), 'cancel'); |
389 |
$dialog->add_button(N("Ok"), 'ok'); |
390 |
$dialog->show_all; |
391 |
if ($dialog->run eq 'ok') { |
392 |
$color = $colorsel->get_current_color; |
393 |
} |
394 |
$dialog->destroy; |
395 |
$color; |
396 |
} |
397 |
|
398 |
my ($scale_r, $scale_t); |
399 |
$scale_r = $scale_t = $height; |
400 |
|
401 |
sub scale_tranmistted($) { $_[0] * $scale_t } |
402 |
sub scale_received($) { $_[0] * $scale_r } |
403 |
|
404 |
sub color_button { |
405 |
my ($gc, $color) = @_; |
406 |
gtknew('Button', relief => 'none', clicked => sub { |
407 |
$color = change_color($color); |
408 |
$gc->set_rgb_fg_color($color); |
409 |
$_[0]->queue_draw; |
410 |
}, |
411 |
child => gtksignal_connect(gtkshow(gtksize(gtkset(Gtk2::DrawingArea->new, width => 10, height => 10), 10, 10)), |
412 |
expose_event => sub { $_[0]->window->draw_rectangle($gc, 1, 0, 0, 10, 10) }) |
413 |
); |
414 |
} |
415 |
|
416 |
|
417 |
sub update() { |
418 |
if (!$during_connection) { |
419 |
my $isconnect = test_connected(0); |
420 |
if ($isconnect != -2) { |
421 |
$isconnected = $isconnect; # save current state |
422 |
$isconnect = test_connected(1); # start new test |
423 |
} |
424 |
} |
425 |
|
426 |
my @intfs = get_val(); # get values from /proc file system |
427 |
foreach (@intfs) { |
428 |
my $intf = $_; |
429 |
if (!member($intf,@interfaces)) { |
430 |
$default_intf ||= $intf; |
431 |
$monitor->{$intf}{initialr} = $monitor->{$intf}{val}[0]; |
432 |
$monitor->{$intf}{initialt} = $monitor->{$intf}{val}[8]; |
433 |
$monitor->{$intf}{totalr} = 0; |
434 |
$monitor->{$intf}{totalt} = 0; |
435 |
$darea->{$intf} = Gtk2::DrawingArea->new; |
436 |
$darea->{$intf}->set_events(["pointer_motion_mask"]); |
437 |
$notebook->append_page(gtkshow(my $page = gtknew('VBox', children => [ |
438 |
0, gtknew('HBox', border_width => 5, children_tight => [ |
439 |
gtksize($darea->{$intf}, $width, $height) ]), |
440 |
0, gtknew('HBox', children => [ |
441 |
1, gtknew('VBox', children_tight => [ |
442 |
gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ |
443 |
color_button($gct, $colort), |
444 |
N("sent: "), $monitor->{$intf}{labelt} = gtknew('Label', text => "0") ]), |
445 |
gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ |
446 |
color_button($gcr, $colorr), |
447 |
N("received: "), $monitor->{$intf}{labelr} = gtknew('Label', text => "0") ]), |
448 |
gtknew('HBox', spacing => 5, border_width => 5, children_tight => [ |
449 |
color_button($gca, $colora), |
450 |
N("average") ]), |
451 |
gtknew('Button', text => N("Reset counters"), sensitive => 1, clicked => sub { intf_reset() }) |
452 |
]), |
453 |
0, gtknew('VBox', border_width => 5, children_tight => [ |
454 |
gtknew('Frame', text => N("Local measure"), shadow_type => 'etched_out', child => |
455 |
gtknew('VBox', border_width => 5, children_tight => [ |
456 |
gtknew('HBox', children_tight => [ |
457 |
N("sent: "), |
458 |
my $measure_t = gtknew('Label', text => "0") |
459 |
]), |
460 |
gtknew('HBox', children_tight => [ |
461 |
N("received: "), |
462 |
my $measure_r = gtknew('Label', text => "0") |
463 |
]) |
464 |
]) |
465 |
) |
466 |
]) |
467 |
]) |
468 |
])), |
469 |
gtknew('Label', text => $intf)); |
470 |
$monitor->{$intf}{page} = $notebook->page_num($page); |
471 |
$darea->{$intf}->realize; |
472 |
$pixmap->{$intf} = Gtk2::Gdk::Pixmap->new($darea->{$intf}->window, $width, $height, $darea->{$intf}->window->get_depth); |
473 |
$monitor->{$intf}{referencer} = $monitor->{$intf}{val}[0]; |
474 |
$monitor->{$intf}{referencet} = $monitor->{$intf}{val}[8]; |
475 |
$pixmap->{$intf}->draw_rectangle($darea->{$intf}->style->black_gc, 1, 0, 0, $width, $height); |
476 |
$darea->{$intf}->signal_connect(motion_notify_event => sub { |
477 |
my (undef, $e) = @_; |
478 |
my $x = $e->x - 50; |
479 |
my $received = $x >= 0 ? $monitor->{$intf}{stack_r}[$x] : 0; |
480 |
my $transmitted = $x >= 0 ? $monitor->{$intf}{stack_t}[$x] : 0; |
481 |
gtkset($measure_r, text => formatXiB($received)); |
482 |
gtkset($measure_t, text => formatXiB($transmitted)); |
483 |
}); |
484 |
$darea->{$intf}->signal_connect(expose_event => sub { |
485 |
return if !$darea->{$intf}->window; |
486 |
$darea->{$intf}->window->draw_drawable($darea->{$intf}->style->bg_gc('normal'), $pixmap->{$intf}, 0, 0, 0, 0, $width, $height); |
487 |
}); |
488 |
$gc_lines->{$intf} = Gtk2::Gdk::GC->new($darea->{$intf}->window); |
489 |
$gc_lines->{$intf}->set_foreground($darea->{$intf}->style->white); |
490 |
$gc_lines->{$intf}->set_line_attributes(1, 'on-off-dash', 'not-last', 'round'); |
491 |
|
492 |
} |
493 |
} |
494 |
foreach (@interfaces) { |
495 |
my $intf = $_; |
496 |
$notebook->remove_page($monitor->{$intf}{page}) unless member($intf,@intfs); |
497 |
} |
498 |
if (@intfs && !@interfaces) { |
499 |
#- select the default interface at start |
500 |
for (my $num_p = 0; $num_p < $notebook->get_n_pages; $num_p++) { |
501 |
if ($notebook->get_tab_label_text($notebook->get_nth_page($num_p)) eq $default_intf) { |
502 |
$notebook->set_current_page($num_p); |
503 |
last; |
504 |
} |
505 |
} |
506 |
} |
507 |
@interfaces = @intfs; |
508 |
if ($isconnected != -2 && $isconnected != -1 && !$during_connection) { |
509 |
if ($isconnected == 1 && !in_ifconfig($net->{net_interface})) { |
510 |
$isconnected = 0; |
511 |
$statusbar->pop(1); |
512 |
$statusbar->push(1, N("Warning, another internet connection has been detected, maybe using your network")); |
513 |
} else { |
514 |
#- translators : $net->{type} is the type of network connection (modem, adsl...) |
515 |
$statusbar->pop(1); |
516 |
$statusbar->push(1, $isconnected == 1 ? N("Connected") : N("Not connected")); |
517 |
} |
518 |
$button_connect->set_sensitive(1); |
519 |
$button_connect->set("label", $isconnected == 1 ? N("Disconnect %s", translate($net->{type})) : N("Connect %s", $net->{type})); |
520 |
} |
521 |
unless ($default_intf || @interfaces) { |
522 |
$button_connect->set_sensitive(0); |
523 |
$button_connect->set("label", N("No internet connection configured")); |
524 |
} |
525 |
1; |
526 |
} |
527 |
|
528 |
sub in_ifconfig { |
529 |
my ($intf) = @_; |
530 |
-x '/sbin/ifconfig' or return 1; |
531 |
$intf eq '' and return 1; |
532 |
`/sbin/ifconfig` =~ /$intf/; |
533 |
} |
534 |
|
535 |
sub draw_monitor { |
536 |
my ($o, $intf) = @_; |
537 |
defined $darea->{$intf} or return; |
538 |
my $gcl = $gc_lines->{$intf}; |
539 |
my $pixmap = $pixmap->{$intf}; |
540 |
my $gc = $darea->{$intf}->style->white_gc; |
541 |
# fix race on ugtk2->exit that causes a crash (#33023) |
542 |
return 0 if !$gc; |
543 |
$pixmap->draw_rectangle($darea->{$intf}->style->black_gc, 1, 0, 0, $width, $height); |
544 |
my $maxr = 0; |
545 |
foreach (@{$o->{stack_r}}) { $maxr = $_ if $_ > $maxr } |
546 |
my $maxt = 0; |
547 |
foreach (@{$o->{stack_t}}) { $maxt = $_ if $_ > $maxt } |
548 |
|
549 |
my ($graph_maxr, $graph_maxt); |
550 |
if ($use_same_scale) { |
551 |
$graph_maxr = $graph_maxt = ($maxr + $maxt)/2; |
552 |
} else { |
553 |
$graph_maxr = $maxr; |
554 |
$graph_maxt = $maxt; |
555 |
} |
556 |
$scale_r = ($height/2) / max($graph_maxr, 1); |
557 |
$scale_t = ($height/2) / max($graph_maxt, 1); |
558 |
|
559 |
my $step = $left_border - 1; |
560 |
foreach (@{$o->{stack_t}}) { |
561 |
$pixmap->draw_rectangle($gct, 1, $step, 0, 1, scale_tranmistted($_)); |
562 |
$step++; |
563 |
} |
564 |
$step = $left_border - 1; |
565 |
my ($av1, $av2, $last_a); |
566 |
foreach (@{$o->{stack_ta}}) { |
567 |
if ($_ != -1) { |
568 |
if (!defined $av1) { $av1 = $_ } else { defined $av2 or $av2 = $_ } |
569 |
if ($av1 && $av2) { |
570 |
$pixmap->draw_line($gca, $step-15, scale_tranmistted($av1), $step-5, scale_tranmistted($av2)); |
571 |
$av1 = $av2; |
572 |
undef $av2; |
573 |
$last_a = $step - $left_border + 1; |
574 |
} |
575 |
} |
576 |
$step++; |
577 |
} |
578 |
$step = $left_border - 1; |
579 |
foreach (@{$o->{stack_r}}) { |
580 |
$pixmap->draw_rectangle($gcr, 1, $step, $height-scale_received($_), 1, scale_received($_)); |
581 |
$step++; |
582 |
} |
583 |
$step = $left_border - 1; |
584 |
$av1 = $av2 = undef; |
585 |
foreach (@{$o->{stack_ra}}) { |
586 |
if ($_ != -1) { |
587 |
if (!defined $av1) { $av1 = $_ } else { defined $av2 or $av2 = $_ } |
588 |
if (defined $av1 && defined $av2) { |
589 |
$pixmap->draw_line($gca, $step-15, $height-scale_received($av1), $step-5, $height-scale_received($av2)); |
590 |
$av1 = $av2; |
591 |
undef $av2; |
592 |
} |
593 |
} |
594 |
$step++; |
595 |
} |
596 |
|
597 |
my ($pix_maxr, $pix_maxt); |
598 |
if ($last_a) { |
599 |
$pix_maxr = $height - scale_received(@{$o->{stack_ra}}[$last_a]); |
600 |
$pix_maxt = scale_tranmistted(@{$o->{stack_ta}}[$last_a]); |
601 |
} else { |
602 |
$pix_maxr = $height - scale_received(@{$o->{stack_r}}[@{$o->{stack_r}}-1]); |
603 |
$pix_maxt = scale_tranmistted(@{$o->{stack_t}}[@{$o->{stack_t}}-1]); |
604 |
} |
605 |
|
606 |
my $x_l = $arrow_size + 1; |
607 |
my $y_l; |
608 |
|
609 |
#- "transmitted" arrow |
610 |
$y_l = max($arrow_space, min($pix_maxt, $pix_maxr - 2*$arrow_size - $arrow_space)); |
611 |
$pixmap->draw_line($gct, $x_l, 0, $x_l, $y_l); |
612 |
$pixmap->draw_line($gct, $x_l-1, 0, $x_l-1, $y_l); |
613 |
$pixmap->draw_line($gct, $x_l+1, 0, $x_l+1, $y_l); |
614 |
$pixmap->draw_polygon($gct, 1, $x_l-$arrow_size, $y_l, $x_l+$arrow_size, $y_l, $x_l, $y_l+$arrow_size); |
615 |
|
616 |
#- "received" arrow |
617 |
$y_l = min($height - $arrow_space, max($pix_maxr, $y_l + 2*$arrow_size + $arrow_space)); |
618 |
$pixmap->draw_line($gcr, $x_l, $height, $x_l, $y_l); |
619 |
$pixmap->draw_line($gcr, $x_l-1, $height, $x_l-1, $y_l); |
620 |
$pixmap->draw_line($gcr, $x_l+1, $height, $x_l+1, $y_l); |
621 |
$pixmap->draw_polygon($gcr, 1, $x_l-$arrow_size, $y_l, $x_l+$arrow_size, $y_l, $x_l, $y_l-$arrow_size); |
622 |
|
623 |
for (my $i = $grid_interval; $i <= $height - $grid_interval; $i += $grid_interval) { |
624 |
$pixmap->draw_line($gcl, $left_border, $i, $width, $i); |
625 |
my ($gc2, $text); |
626 |
if ($i > max($grid_interval, $use_same_scale ? $pix_maxt : $height/2)) { |
627 |
$text = formatXiB(($height-$i)/$scale_r); |
628 |
$gc2 = $gcr; |
629 |
} else { |
630 |
$text = formatXiB($i/$scale_t); |
631 |
$gc2 = $gct; |
632 |
} |
633 |
$pixmap->draw_layout($gc2, 45-string_width($darea->{$intf}, $text), $i-5, $darea->{$intf}->create_pango_layout($text)); |
634 |
} |
635 |
$darea->{$intf}->queue_draw; |
636 |
} |
637 |
|
638 |
|
639 |
sub test_connected { |
640 |
my ($arg) = @_; |
641 |
$::testing || network::tools::test_connected($arg); |
642 |
} |