Editorial stuff.
[obnox/wireshark/wip.git] / gtk / sctp_chunk_stat_dlg.c
1 /* 
2  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
3  *
4  * $Id: sctp_chunk_stat_dlg.c 13531 2005-02-27 13:57:45Z lego $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24  
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <gtk/gtk.h>
30 #include <string.h>
31
32 #include "globals.h"
33 #include "epan/filesystem.h"
34
35 #include "image/clist_ascend.xpm"
36 #include "image/clist_descend.xpm"
37
38 #include "tap_menu.h"
39 #include "dlg_utils.h"
40 #include "ui_util.h"
41 #include "main.h"
42 #include "compat_macros.h"
43
44 #include "sctp_stat.h"
45
46
47 static GtkWidget *sctp_chunk_stat_dlg=NULL;
48 static GtkWidget *clist = NULL;
49 static GList *last_list = NULL;
50 static sctp_assoc_info_t* selected_stream = NULL;  /* current selection */
51 extern GtkWidget *main_display_filter_widget;
52
53 #define NUM_COLS   14
54 #define FRAME_LIMIT 8
55
56 enum chunk_types {
57         DATA          = 0,
58         INIT          = 1,
59         INIT_ACK      = 2,
60         SACK          = 3,
61         HEARTBEAT     = 4,
62         HEARTBEAT_ACK = 5,
63         ABORT         = 6,
64         SHUTDOWN      = 7,
65         SHUTDOWN_ACK  = 8,
66         SCTP_ERROR    = 9,
67         COOKIE_ECHO   = 10,
68         COOKIE_ACK    = 11
69 };
70
71 char *chunk_name(int type)
72 {
73 #define CASE(x) case x: s=#x; break
74         char *s = "unknown";
75         switch (type)
76         {
77                 CASE(DATA);
78                 CASE(INIT);
79                 CASE(INIT_ACK);
80                 CASE(SACK);
81                 CASE(HEARTBEAT);
82                 CASE(HEARTBEAT_ACK);
83                 CASE(ABORT);
84                 CASE(SHUTDOWN);
85                 CASE(SHUTDOWN_ACK);
86                 CASE(SCTP_ERROR);
87                 CASE(COOKIE_ECHO);
88                 CASE(COOKIE_ACK);
89         }
90         return s;
91 }
92
93 typedef struct column_arrows {
94         GtkWidget *table;
95         GtkWidget *ascend_pm;
96         GtkWidget *descend_pm;
97 } column_arrows;
98
99
100 static void
101 chunk_dlg_destroy(GtkObject *object _U_, gpointer user_data)
102 {
103         struct sctp_udata *u_data=(struct sctp_udata*)user_data;
104         decrease_childcount(u_data->parent);
105         remove_child(u_data, u_data->parent);
106         g_free(u_data->io);
107         g_free(u_data);
108 }
109
110 static void
111 on_destroy(GtkObject *object _U_, gpointer user_data)
112 {
113         struct sctp_udata *u_data=(struct sctp_udata*)user_data;
114         decrease_childcount(u_data->parent);
115         remove_child(u_data, u_data->parent);
116         g_free(u_data->io);
117         g_free(u_data);
118 }
119
120
121 static void add_to_clist(sctp_addr_chunk* sac)
122 {
123         gint added_row, i;
124         gchar *data[NUM_COLS];
125         gchar field[NUM_COLS][MAX_ADDRESS_LEN];
126
127         for (i=0; i<NUM_COLS; i++)
128                 data[i]=&field[i][0];
129                 
130         if (sac->addr->type==AT_IPv4)
131         {
132                 g_snprintf(field[0], MAX_ADDRESS_LEN, "%s", ip_to_str((const guint8 *)(sac->addr->data)));
133         }
134         else if (sac->addr->type==AT_IPv6)
135         {
136                 g_snprintf(field[0], MAX_ADDRESS_LEN, "%s", ip6_to_str((const struct e_in6_addr *)(sac->addr->data)));
137         }
138
139         for (i=1; i<NUM_COLS-1; i++)
140                 g_snprintf(field[i], MAX_ADDRESS_LEN, "%u", sac->addr_count[i-1]);
141         
142         g_snprintf(field[NUM_COLS-1], MAX_ADDRESS_LEN, "%u", sac->addr_count[12]);
143         added_row = gtk_clist_append(GTK_CLIST(clist), data);
144         gtk_clist_set_row_data(GTK_CLIST(clist), added_row, sac);
145 }
146
147 void sctp_chunk_stat_dlg_update(struct sctp_udata* udata, unsigned int direction)
148 {
149         GList *list=NULL;
150         sctp_addr_chunk* sac;
151
152         if (udata->io->window != NULL)
153         {
154                 gtk_clist_clear(GTK_CLIST(clist));
155                 if (udata->assoc->addr_chunk_count!=NULL)
156                 {
157                         list = g_list_first(udata->assoc->addr_chunk_count);
158         
159                         while (list)
160                         {
161                                 sac = (sctp_addr_chunk*)(list->data);
162                                 if (sac->direction==direction)
163                                 {
164                                         add_to_clist(sac);
165                                         list = g_list_next(list);
166                                 }
167                                 else
168                                         list = g_list_next(list);
169                         }
170                 }
171         }
172         last_list = list;
173 }
174
175
176
177 static void
178 sctp_chunk_stat_on_close (GtkButton *button _U_, gpointer         user_data)
179 {
180         struct sctp_udata *udata;
181
182         udata = (struct sctp_udata *)user_data;
183         gtk_grab_remove(udata->io->window);
184         gtk_widget_destroy(udata->io->window);
185 }
186
187 static void
188 on_close_dlg (GtkButton *button _U_, gpointer user_data)
189 {
190         struct sctp_udata *udata;
191
192         udata = (struct sctp_udata *)user_data;
193         gtk_grab_remove(udata->io->window);
194         gtk_widget_destroy(udata->io->window);
195 }
196
197
198 static void path_window_set_title(struct sctp_udata *u_data, unsigned int direction)
199 {
200         char *title;
201         if(!u_data->io->window){
202                 return;
203         }
204         title = g_strdup_printf("SCTP Path Chunk Statistics for Endpoint %u: %s Port1 %u  Port2 %u",direction,
205                                 cf_get_display_name(&cfile), u_data->assoc->port1, u_data->assoc->port2);
206         gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
207         g_free(title);
208 }
209
210 static void
211 gtk_sctpstat_dlg(struct sctp_udata *u_data, unsigned int direction)
212 {
213         GtkWidget *vbox1;
214         GtkWidget *scrolledwindow1;
215         GtkWidget *hbuttonbox2;
216         GtkWidget *bt_close;
217
218         gchar *titles[NUM_COLS] =  {"IP Address", "DATA", "INIT", "INIT_ACK", "SACK", "HEARTBEAT", "HEARTBEAT_ACK", "ABORT", "SHUTDOWN", "SHUTDOWN_ACK", "ERROR", "COOKIE_ECHO", "COOKIE_ACK", "Others"};
219         column_arrows *col_arrows;
220         GdkBitmap *ascend_bm, *descend_bm;
221         GdkPixmap *ascend_pm, *descend_pm;
222         GtkStyle *win_style;
223         GtkWidget *column_lb;
224         int i;
225
226         sctp_graph_t* io=g_malloc(sizeof(sctp_graph_t));
227         io->window=NULL;
228         u_data->io=io;
229         u_data->io->window= gtk_window_new (GTK_WINDOW_TOPLEVEL);
230         gtk_window_set_position (GTK_WINDOW (u_data->io->window), GTK_WIN_POS_CENTER);
231         path_window_set_title(u_data, direction);
232         SIGNAL_CONNECT(u_data->io->window, "destroy", chunk_dlg_destroy,u_data);
233
234         /* Container for each row of widgets */
235         vbox1 = gtk_vbox_new(FALSE, 2);
236         gtk_container_border_width(GTK_CONTAINER(vbox1), 8);
237         gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox1);
238         gtk_widget_show(vbox1);
239
240         scrolledwindow1 = scrolled_window_new (NULL, NULL);
241         gtk_widget_show (scrolledwindow1);
242         gtk_box_pack_start (GTK_BOX (vbox1), scrolledwindow1, TRUE, TRUE, 0);
243
244         clist = gtk_clist_new (NUM_COLS);
245         gtk_widget_show (clist);
246         gtk_container_add (GTK_CONTAINER (scrolledwindow1), clist);
247         WIDGET_SET_SIZE(clist, 850, 200);
248
249         gtk_clist_set_column_width (GTK_CLIST (clist), 0, 135);
250         gtk_clist_set_column_width (GTK_CLIST (clist), 1, 35);
251         gtk_clist_set_column_width (GTK_CLIST (clist), 2, 25);
252         gtk_clist_set_column_width (GTK_CLIST (clist), 3, 50);
253         gtk_clist_set_column_width (GTK_CLIST (clist), 4, 35);
254         gtk_clist_set_column_width (GTK_CLIST (clist), 5, 60);
255         gtk_clist_set_column_width (GTK_CLIST (clist), 6, 90);
256         gtk_clist_set_column_width (GTK_CLIST (clist), 7, 40);
257         gtk_clist_set_column_width (GTK_CLIST (clist), 8, 65);
258         gtk_clist_set_column_width (GTK_CLIST (clist), 9, 90);
259         gtk_clist_set_column_width (GTK_CLIST (clist), 10, 40);
260         gtk_clist_set_column_width (GTK_CLIST (clist), 11, 80);
261         gtk_clist_set_column_width (GTK_CLIST (clist), 12, 70);
262         gtk_clist_set_column_width (GTK_CLIST (clist), 13, 35);
263
264         gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_LEFT);
265         gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_CENTER);
266         gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_CENTER);
267         gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_CENTER);
268         gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_CENTER);
269         gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER);
270         gtk_clist_set_column_justification(GTK_CLIST(clist), 6, GTK_JUSTIFY_CENTER);
271         gtk_clist_set_column_justification(GTK_CLIST(clist), 7, GTK_JUSTIFY_CENTER);
272         gtk_clist_set_column_justification(GTK_CLIST(clist), 8, GTK_JUSTIFY_CENTER);
273         gtk_clist_set_column_justification(GTK_CLIST(clist), 9, GTK_JUSTIFY_CENTER);
274         gtk_clist_set_column_justification(GTK_CLIST(clist), 10, GTK_JUSTIFY_CENTER);
275         gtk_clist_set_column_justification(GTK_CLIST(clist), 11, GTK_JUSTIFY_CENTER);
276         gtk_clist_set_column_justification(GTK_CLIST(clist), 12, GTK_JUSTIFY_CENTER);
277         gtk_clist_set_column_justification(GTK_CLIST(clist), 13, GTK_JUSTIFY_CENTER);
278         
279         gtk_clist_column_titles_show (GTK_CLIST (clist));
280
281         gtk_widget_show(u_data->io->window);
282
283         col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
284         win_style = gtk_widget_get_style(scrolledwindow1);
285
286         ascend_pm = gdk_pixmap_create_from_xpm_d(scrolledwindow1->window,
287                                                  &ascend_bm,
288                                                  &win_style->bg[GTK_STATE_NORMAL],
289                                                  (gchar **)clist_ascend_xpm);
290         descend_pm = gdk_pixmap_create_from_xpm_d(scrolledwindow1->window,
291                                                   &descend_bm,
292                                                   &win_style->bg[GTK_STATE_NORMAL],
293                                                   (gchar **)clist_descend_xpm);
294         for (i=0; i<NUM_COLS; i++)
295         {
296                 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
297                 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
298                 column_lb = gtk_label_new(titles[i]);
299                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
300                 gtk_widget_show(column_lb);
301                 col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
302                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
303                 col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
304                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
305                 /* make src-ip be the default sort order */
306                 if (i == 0)
307                 {
308                         gtk_widget_show(col_arrows[i].ascend_pm);
309                 }
310
311                 gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
312                 gtk_widget_show(col_arrows[i].table);
313         }
314
315         hbuttonbox2 = gtk_hbutton_box_new();
316         gtk_box_pack_start(GTK_BOX(vbox1), hbuttonbox2, FALSE, FALSE, 0);
317         gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox2), 10);
318         gtk_button_box_set_layout(GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
319         gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbuttonbox2), 0);
320         gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (hbuttonbox2), 4, 0);
321         gtk_widget_show(hbuttonbox2);
322
323         bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
324         gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_close);
325         gtk_widget_show (bt_close);
326
327         SIGNAL_CONNECT(bt_close, "clicked", sctp_chunk_stat_on_close, u_data);
328
329         cf_retap_packets(&cfile);
330
331 }
332
333
334 static void chunk_window_set_title(struct sctp_udata *u_data)
335 {
336         char *title;
337         if(!u_data->io->window){
338                 return;
339         }
340         title = g_strdup_printf("SCTP Association Chunk Statistics: %s Port1 %u  Port2 %u",
341                                 cf_get_display_name(&cfile), u_data->assoc->port1, u_data->assoc->port2);
342         gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
343         g_free(title);
344 }
345
346 void sctp_chunk_dlg(struct sctp_udata *u_data)
347 {
348         GtkWidget *main_vb, *table;
349         GtkWidget *label, *h_button_box;
350         GtkWidget *close_bt;
351         gchar label_txt[50];
352         int i, row;
353         
354         sctp_graph_t* io=g_malloc(sizeof(sctp_graph_t));
355         io->window=NULL;
356         u_data->io=io;
357         u_data->io->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
358         gtk_window_set_position (GTK_WINDOW (u_data->io->window), GTK_WIN_POS_CENTER);
359         WIDGET_SET_SIZE(u_data->io->window, 500, 400);
360         SIGNAL_CONNECT(u_data->io->window, "destroy", on_destroy,u_data);
361
362         /* Container for each row of widgets */
363         main_vb = gtk_vbox_new(FALSE, 12);
364         gtk_container_border_width(GTK_CONTAINER(main_vb), 12);
365         gtk_container_add(GTK_CONTAINER(u_data->io->window), main_vb);
366          
367          /* table */
368         table = gtk_table_new(1, 4, FALSE);
369         gtk_table_set_col_spacings(GTK_TABLE(table), 6);
370         gtk_table_set_row_spacings(GTK_TABLE(table), 3);
371         gtk_container_add(GTK_CONTAINER(main_vb), table);
372         row = 0;
373                         
374         label = gtk_label_new("ChunkType");
375         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
376         gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, row, row+1);   
377         label = gtk_label_new("Association");
378         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
379         gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, row, row+1);
380         label = gtk_label_new("Endpoint 1");
381         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
382         gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, row, row+1);
383         label = gtk_label_new("Endpoint 2");
384         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
385         gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, row, row+1);
386         row ++;
387         label = gtk_label_new("");
388         gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, row, row+1);   
389         label = gtk_label_new("");
390         gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, row, row+1);
391         label = gtk_label_new("");
392         gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, row, row+1);
393         label = gtk_label_new("");
394         gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, row, row+1);
395         row ++;
396
397         for (i=0; i<NUM_CHUNKS-1; i++)
398         {
399                 label = gtk_label_new(chunk_name(i));
400                 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
401                 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, row, row+1);   
402                 g_snprintf(label_txt, 10, "%u", selected_stream->chunk_count[i]);
403                 label = gtk_label_new(label_txt);
404                 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
405                 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, row, row+1);
406                 g_snprintf(label_txt, 10, "%u", selected_stream->ep1_chunk_count[i]);
407                 label = gtk_label_new(label_txt);
408                 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
409                 gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, row, row+1);
410                 g_snprintf(label_txt, 10, "%u", selected_stream->ep2_chunk_count[i]);
411                 label = gtk_label_new(label_txt);
412                 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
413                 gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, row, row+1);
414                 row ++;
415         }
416         
417         label = gtk_label_new("Others");
418         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
419         gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, row, row+1);
420         g_snprintf(label_txt, 10, "%u", selected_stream->chunk_count[12]);
421         label = gtk_label_new(label_txt);
422         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
423         gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, row, row+1);
424         g_snprintf(label_txt, 10, "%u", selected_stream->ep1_chunk_count[12]);
425         label = gtk_label_new(label_txt);
426         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
427         gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, row, row+1);
428         g_snprintf(label_txt, 10, "%u", selected_stream->ep2_chunk_count[12]);
429         label = gtk_label_new(label_txt);
430         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
431         gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, row, row+1);
432         
433         h_button_box=gtk_hbutton_box_new();
434         gtk_box_pack_start(GTK_BOX(main_vb), h_button_box, FALSE, FALSE, 0);
435         gtk_container_set_border_width(GTK_CONTAINER(h_button_box), 10);
436         gtk_button_box_set_layout(GTK_BUTTON_BOX (h_button_box), GTK_BUTTONBOX_SPREAD);
437         gtk_button_box_set_spacing(GTK_BUTTON_BOX (h_button_box), 0);
438         gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (h_button_box), 4, 0);
439         gtk_widget_show(h_button_box);
440         
441         close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
442         gtk_box_pack_start(GTK_BOX(h_button_box), close_bt, FALSE, FALSE, 0);
443         gtk_widget_show(close_bt);
444         SIGNAL_CONNECT(close_bt, "clicked", on_close_dlg, u_data);
445         
446         gtk_widget_show_all(u_data->io->window);
447         chunk_window_set_title(u_data);
448 }
449
450 void sctp_chunk_dlg_show(struct sctp_analyse* userdata)
451 {
452         gint i;
453         struct sctp_udata *u_data;
454
455         u_data=g_malloc(sizeof(struct sctp_udata));
456         u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
457         u_data->assoc=userdata->assoc;
458         u_data->io=NULL;
459         u_data->parent = userdata;
460
461         if (selected_stream==NULL)
462                 selected_stream=g_malloc(sizeof(sctp_assoc_info_t));
463
464         selected_stream=u_data->assoc;
465         for (i=0; i<NUM_CHUNKS; i++)
466         {
467                 selected_stream->chunk_count[i]=u_data->assoc->chunk_count[i];
468         }
469         set_child(u_data, u_data->parent);
470         increase_childcount(u_data->parent);
471         sctp_chunk_dlg(u_data);
472 }
473
474 void sctp_chunk_stat_dlg_show(unsigned int direction, struct sctp_analyse* userdata)
475 {
476         struct sctp_udata *u_data;
477
478         u_data=g_malloc(sizeof(struct sctp_udata));
479         u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
480         u_data->assoc=userdata->assoc;
481         u_data->io=NULL;
482         u_data->parent = userdata;
483         
484         if (selected_stream==NULL)
485                 selected_stream=g_malloc(sizeof(sctp_assoc_info_t));
486         selected_stream=u_data->assoc;
487         selected_stream->addr_chunk_count=u_data->assoc->addr_chunk_count;
488
489         set_child(u_data, u_data->parent);
490         increase_childcount(u_data->parent);
491         gtk_sctpstat_dlg(u_data, direction);
492         sctp_chunk_stat_dlg_update(u_data,direction);
493 }
494
495 GtkWidget* get_chunk_stat_dlg(void)
496 {
497         return sctp_chunk_stat_dlg;
498 }