remove old gtkstyle hack.
[lxde/lxpanel.git] / src / plugins / netstat / netstat.c
1 /**
2 * Copyright (c) 2008 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #if HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <pthread.h>
29 #include <iwlib.h>
30 #include "nsconfig.h"
31 #include "netstat.h"
32 #include "lxnm_client.h"
33 #include "statusicon.h"
34 #include "passwd_gui.h"
35 #include "devproc.h"
36 #include "wireless.h"
37 #include "panel.h"
38 #include "misc.h"
39 #include "plugin.h"
40 #include "dbg.h"
41
42 /* 1 second */
43 #define NETSTAT_IFACE_POLL_DELAY 1000
44
45 static int actionProcess(void *arg)
46 {
47 ENTER;
48 RET(system((char *)arg));
49 }
50
51 /* menu handlers */
52 static void fixconn(GtkWidget *widget, netdev_info *ni)
53 {
54 pthread_t actionThread;
55 char *fixcmd;
56
57 fixcmd = g_strdup_printf(ni->ns->fixcmd, ni->netdev_list->info.ifname);
58
59 pthread_create(&actionThread, NULL, actionProcess, fixcmd);
60 }
61
62 static void wireless_connect(GtkWidget *widget, ap_setting *aps)
63 {
64
65 char *cmdargs;
66
67 /* without encryption */
68 if (aps->en_type==NS_WIRELESS_AUTH_OFF) {
69 if (strlen(aps->essid)!=0)
70 cmdargs = g_strdup_printf("%s %s OFF NULL %s", aps->ifname, asc2hex(aps->essid), aps->apaddr);
71 else
72 cmdargs = g_strdup_printf("%s NULL OFF NULL %s", aps->ifname, aps->apaddr);
73
74 lxnm_send_command(aps->gio, LXNM_WIRELESS_CONNECT, cmdargs);
75 } else {
76 /* with encryption */
77
78 if (aps->ni->netdev_list->info.pg!=NULL)
79 passwd_gui_destroy(aps->ni->netdev_list->info.pg);
80
81 /* create dialog window for typing password */
82 aps->ni->netdev_list->info.pg = passwd_gui_new(aps);
83 //passwd_gui_set_style(aps->ni->netdev_list->info.pg, gtk_style_new());
84 }
85 }
86
87 static gint menupopup(GtkWidget *widget, GdkEvent *event, netdev_info *ni)
88 {
89 GdkEventButton *event_button;
90
91 g_return_val_if_fail (event != NULL, FALSE);
92
93 if (event->type == GDK_BUTTON_PRESS) {
94 event_button = (GdkEventButton *) event;
95 if (event_button->button == 1) {
96 /* wireless device */
97 if (ni->netdev_list->info.wireless) {
98 GtkWidget *menu;
99 GtkWidget *menu_ap;
100 APINFOLIST *aplist;
101 APINFOLIST *ptr;
102
103 /* create menu */
104 menu = gtk_menu_new();
105
106 /* Scanning AP */
107 aplist = wireless_ap_scanning(ni->ns->fnetd->iwsockfd, ni->netdev_list->info.ifname);
108 if (aplist!=NULL) {
109 ptr = aplist;
110 do {
111 GtkWidget *item_box;
112 GtkWidget *essid_label;
113 GtkWidget *lockicon;
114 GtkWidget *signal_quality;
115 gdouble quality_per;
116 ap_setting *aps;
117
118 aps = malloc(sizeof(ap_setting));
119 aps->ni = ni;
120 aps->ifname = ni->netdev_list->info.ifname;
121 aps->gio = ni->ns->fnetd->lxnmchannel;
122 aps->apaddr = ptr->info.apaddr;
123 aps->en_type = ptr->info.en_method;
124
125 menu_ap = gtk_menu_item_new();
126 item_box = gtk_hbox_new(FALSE, 0);
127
128 /* Encryption */
129 if (ptr->info.haskey) {
130 lockicon = gtk_image_new_from_file(ICONS_WL_LOCK);
131 gtk_box_pack_start(GTK_BOX(item_box), lockicon, FALSE, FALSE, 0);
132 if (aps->en_type==NS_WIRELESS_AUTH_OFF)
133 aps->en_type = NS_WIRELESS_AUTH_WEP;
134 }
135
136 /* ESSID */
137 aps->essid = ptr->info.essid;
138 if (strlen(aps->essid)!=0)
139 essid_label = gtk_label_new(ptr->info.essid);
140 else
141 essid_label = gtk_label_new(_("<Hidden Access Point>"));
142 // gtk_misc_set_alignment(GTK_MISC(essid_label), 0, 0);
143 gtk_label_set_justify(essid_label, GTK_JUSTIFY_LEFT);
144 gtk_misc_set_padding(GTK_MISC(essid_label), 2, 0);
145 gtk_box_pack_start(GTK_BOX(item_box), essid_label, TRUE, FALSE, 0);
146
147 /* Quality */
148 quality_per = (gdouble)((double)ptr->info.quality/100);
149 if (quality_per>1)
150 quality_per = 1;
151 else if (quality_per<0)
152 quality_per = 0;
153
154 signal_quality = gtk_progress_bar_new();
155 gtk_widget_set_size_request(signal_quality, 100, -1);
156 gtk_progress_bar_set_orientation(signal_quality, GTK_PROGRESS_LEFT_TO_RIGHT);
157 gtk_progress_bar_set_fraction(signal_quality, quality_per);
158 gtk_box_pack_start(GTK_BOX(item_box), signal_quality, FALSE, FALSE, 0);
159
160 gtk_container_add(GTK_CONTAINER(menu_ap), item_box);
161 gtk_menu_append(GTK_MENU(menu), menu_ap);
162 g_signal_connect(G_OBJECT(menu_ap), "activate", G_CALLBACK(wireless_connect), aps);
163 g_object_weak_ref(menu_ap, g_free, aps);
164 ptr = ptr->next;
165 } while(ptr!=NULL);
166 }
167 gtk_widget_show_all(menu);
168
169 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
170 }
171 } else if (event_button->button == 3) {
172 GtkWidget *menu;
173 GtkWidget *menu_fix;
174
175 /* create menu */
176 menu = gtk_menu_new();
177
178 /* Repair */
179 menu_fix = gtk_menu_item_new_with_label(_("Repair"));
180 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_fix);
181 g_signal_connect(G_OBJECT(menu_fix), "activate", G_CALLBACK(fixconn), ni);
182
183 gtk_widget_show_all(menu);
184
185 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
186 return TRUE;
187 }
188 }
189
190 return FALSE;
191 }
192
193 static char *select_icon(gboolean plug, gboolean connected, int stat)
194 {
195 if (!plug)
196 return ICONS_DISCONNECT;
197
198 switch(stat) {
199 case NETDEV_STAT_NORMAL:
200 return ICONS_CONNECTED;
201 break;
202 case NETDEV_STAT_PROBLEM:
203 return ICONS_PROBLEM;
204 break;
205 case NETDEV_STAT_RENEW:
206 return ICONS_RENEW;
207 break;
208 case NETDEV_STAT_BOTHRS:
209 return ICONS_BOTHRS;
210 break;
211 case NETDEV_STAT_SENDDATA:
212 return ICONS_SENDDATA;
213 break;
214 case NETDEV_STAT_RECVDATA:
215 return ICONS_RECVDATA;
216 break;
217 }
218 }
219
220 static void refresh_systray(netstat *ns, NETDEVLIST_PTR netdev_list)
221 {
222 NETDEVLIST_PTR ptr;
223 char *tooltip;
224
225 if (netdev_list==NULL) {
226 return;
227 }
228
229 ptr = netdev_list;
230 do {
231 if (!ptr->info.enable) {
232 if (ptr->info.status_icon!=NULL) {
233 set_statusicon_visible(ptr->info.status_icon, FALSE);
234 }
235 } else if (ptr->info.updated) {
236 if (!ptr->info.plug)
237 tooltip = g_strdup_printf("%s\n %s", ptr->info.ifname, _("Network cable is plugged out"));
238 else if (!ptr->info.connected)
239 tooltip = g_strdup_printf("%s\n %s", ptr->info.ifname, _("Connection has limited or no connectivity"));
240 else if (ptr->info.flags & IFF_POINTOPOINT)
241 tooltip = g_strdup_printf("%s\n %s\t%s\n %s\t%s\n %s\t%s\n\n %s(%s/%s)\n %d/%d %s\n %d/%d %s",
242 ptr->info.ifname,
243 _("IP Address:"), ptr->info.ipaddr,
244 _("Remote IP:"), ptr->info.dest,
245 _("Netmask:"), ptr->info.mask,
246 _("Activity"), _("Sent"),_("Received"),
247 ptr->info.trans_bytes, ptr->info.recv_bytes, _("bytes"),
248 ptr->info.trans_packets, ptr->info.recv_packets, _("packets"));
249 else if (ptr->info.wireless)
250 tooltip = g_strdup_printf("%s(%s) - %s(%d%%)\n %s\t%s\n %s\t%s\n %s\t%s\n %s\t%s\n %s\t%s\n\n %s(%s/%s)\n %d/%d %s\n %d/%d %s",
251 ptr->info.ifname, _("Wireless"),
252 ptr->info.essid, ptr->info.quality,
253 _("Protocol:"), ptr->info.protocol,
254 _("IP Address:"), ptr->info.ipaddr,
255 _("Boradcast:"), ptr->info.bcast,
256 _("Netmask:"), ptr->info.mask,
257 _("HW Address:"), ptr->info.mac,
258 _("Activity"), _("Sent"), _("Received"),
259 ptr->info.trans_bytes, ptr->info.recv_bytes, _("bytes"),
260 ptr->info.trans_packets, ptr->info.recv_packets, _("packets"));
261
262 else
263 tooltip = g_strdup_printf("%s\n %s\t%s\n %s\t%s\n %s\t%s\n %s\t%s\n\n %s(%s/%s)\n %d/%d %s\n %d/%d %s",
264 ptr->info.ifname,
265 _("IP Address:"), ptr->info.ipaddr,
266 _("Boradcast:"), ptr->info.bcast,
267 _("Netmask:"), ptr->info.mask,
268 _("HW Address:"), ptr->info.mac,
269 _("Activity"), _("Sent"), _("Received"),
270 ptr->info.trans_bytes, ptr->info.recv_bytes, _("bytes"),
271 ptr->info.trans_packets, ptr->info.recv_packets, _("packets"));
272
273 /* status icon doesn't exist */
274 if (ptr->info.status_icon==NULL) {
275 netdev_info *ni;
276 ni = malloc(sizeof(netdev_info));
277 ni->ns = ns;
278 ni->netdev_list = ptr;
279
280 ptr->info.status_icon = create_statusicon(ns->mainw, select_icon(ptr->info.plug, ptr->info.connected, ptr->info.status), tooltip);
281 g_signal_connect(ptr->info.status_icon->main, "button_press_event", G_CALLBACK(menupopup), ni);
282 } else {
283 set_statusicon_tooltips(ptr->info.status_icon, tooltip);
284 set_statusicon_image_from_file(ptr->info.status_icon, select_icon(ptr->info.plug, ptr->info.connected, ptr->info.status));
285 set_statusicon_visible(ptr->info.status_icon, TRUE);
286 }
287 g_free(tooltip);
288 }
289 ptr = ptr->next;
290 } while(ptr!=NULL);
291 }
292
293 static gboolean refresh_devstat(netstat *ns)
294 {
295 netproc_listener(ns->fnetd);
296 //netproc_print(fnetd->netdevlist);
297 refresh_systray(ns, ns->fnetd->netdevlist);
298 netproc_devicelist_clear(&ns->fnetd->netdevlist);
299 return TRUE;
300 }
301
302 /* Plugin constructor */
303 static void netstat_destructor(plugin *p)
304 {
305 netstat *ns = (netstat *) p->priv;
306
307 ENTER;
308 g_source_remove(ns->ttag);
309 netproc_netdevlist_clear(&ns->fnetd->netdevlist);
310 /* The widget is destroyed in plugin_stop().
311 gtk_widget_destroy(ns->mainw);
312 */
313 lxnm_close(ns->fnetd->lxnmchannel);
314 close(ns->fnetd->sockfd);
315 close(ns->fnetd->iwsockfd);
316 g_free(ns->fnetd);
317 g_free(ns->fixcmd);
318 g_free(ns);
319 RET();
320 }
321
322 static int netstat_constructor(plugin *p, char **fp)
323 {
324 netstat *ns;
325 line s;
326
327 ENTER;
328 s.len = 256;
329 ns = g_new0(netstat, 1);
330 g_return_val_if_fail(ns != NULL, 0);
331 p->priv = ns;
332
333 if( fp ) {
334 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
335 if (s.type == LINE_NONE) {
336 ERR( "netstat: illegal token %s\n", s.str);
337 goto error;
338 }
339 if (s.type == LINE_VAR) {
340 if (!g_ascii_strcasecmp(s.t[0], "FixCommand"))
341 ns->fixcmd = g_strdup(s.t[1]);
342 else {
343 ERR( "netstat: unknown var %s\n", s.t[0]);
344 goto error;
345 }
346 } else {
347 ERR( "netstat: illegal in this context %s\n", s.str);
348 goto error;
349 }
350 }
351 }
352
353 /* initializing */
354 ns->fnetd = malloc(sizeof(FNETD));
355 ns->fnetd->netdevlist = NULL;
356 ns->fnetd->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
357 ns->fnetd->iwsockfd = iw_sockets_open();
358 ns->fnetd->lxnmchannel = lxnm_socket();
359
360 /* main */
361 ns->mainw = p->panel->my_box_new(FALSE, 1);
362 gtk_widget_show_all(ns->mainw);
363
364 /* Initializing network device list*/
365 ns->fnetd->netdev_fp = netproc_open();
366 ns->fnetd->dev_count = netproc_netdevlist_clear(&ns->fnetd->netdevlist);
367 ns->fnetd->dev_count = netproc_scandevice(ns->fnetd->sockfd, ns->fnetd->iwsockfd, ns->fnetd->netdev_fp, &ns->fnetd->netdevlist);
368 netproc_close(ns->fnetd->netdev_fp);
369 refresh_systray(ns, ns->fnetd->netdevlist);
370
371 ns->ttag = g_timeout_add(NETSTAT_IFACE_POLL_DELAY, (GSourceFunc)refresh_devstat, ns);
372
373 p->pwid = ns->mainw;
374
375 RET(1);
376 error:
377 g_free(ns->fnetd);
378 g_free(ns->fixcmd);
379 g_free(ns);
380 RET(0);
381 }
382
383 plugin_class netstat_plugin_class = {
384 fname: NULL,
385 count: 0,
386
387 type : "netstat",
388 name : N_("Net Status Monitor"),
389 version: "1.0",
390 description : N_("Monitor network status"),
391
392 constructor : netstat_constructor,
393 destructor : netstat_destructor,
394 config : NULL,
395 save : NULL
396 };