2 * Graphic Analysis addition for ethereal
6 * Copyright 2004, Verso Technologies Inc.
7 * By Alejandro Vaquero <alejandrovaquero@yahoo.com>
9 * based on rtp_analysis.c and io_stat
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@ethereal.com>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include "graph_analysis.h"
37 #include <epan/epan_dissect.h>
38 #include <epan/filesystem.h>
43 #include <epan/dissectors/packet-rtp.h>
47 #include "gtkglobals.h"
49 #include "dlg_utils.h"
51 #include "alert_box.h"
52 #include "simple_dialog.h"
55 #include "progress_dlg.h"
56 #include "compat_macros.h"
59 #include "image/clist_ascend.xpm"
60 #include "image/clist_descend.xpm"
75 #include <io.h> /* open/close on win32 */
78 /* Win32 needs the O_BINARY flag for open() */
83 /****************************************************************************/
86 #define OK_TEXT "[ Ok ]"
87 #define PT_UNDEFINED -1
90 #if GTK_MAJOR_VERSION < 2
92 GdkColormap *colormap;
95 typedef const guint8 * ip_addr_p;
98 /****************************************************************************/
99 /* Reset the user_data structure */
100 static void graph_analysis_reset(graph_analysis_data_t* user_data)
104 user_data->num_nodes = 0;
105 user_data->num_items = 0;
106 for (i=0; i<MAX_NUM_NODES; i++){
107 user_data->nodes[i] = 0;
110 user_data->dlg.first_node=0;
111 user_data->dlg.first_item=0;
112 user_data->dlg.left_x_border=0;
113 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
116 /****************************************************************************/
117 /* Reset the user_data structure */
118 static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
120 /* init dialog_graph */
121 user_data->dlg.needs_redraw=TRUE;
122 user_data->dlg.draw_area=NULL;
123 user_data->dlg.pixmap=NULL;
124 user_data->dlg.h_scrollbar=NULL;
125 user_data->dlg.h_scrollbar_adjustment=NULL;
126 user_data->dlg.v_scrollbar=NULL;
127 user_data->dlg.v_scrollbar_adjustment=NULL;
128 user_data->dlg.pixmap_width=600;
129 user_data->dlg.pixmap_height=400;
130 user_data->dlg.first_node=0;
131 user_data->dlg.first_item=0;
132 user_data->dlg.left_x_border=0;
133 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
134 user_data->dlg.window=NULL;
137 /****************************************************************************/
141 /****************************************************************************/
142 /* close the dialog window and remove the tap listener */
143 static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
150 /****************************************************************************/
151 static void dialog_graph_set_title(graph_analysis_data_t* user_data)
154 if (!user_data->dlg.window){
157 title = g_strdup_printf("Ale");
159 gtk_window_set_title(GTK_WINDOW(user_data->dlg.window), title);
163 #define RIGHT_ARROW 1
165 #define WIDTH_ARROW 8
166 #define HEIGHT_ARROW 6
168 /****************************************************************************/
169 static void draw_arrow(GdkDrawable *pixmap, GdkGC *gc, gint x, gint y, gboolean direction)
171 GdkPoint arrow_point[3];
173 arrow_point[0].x = x;
174 arrow_point[0].y = y-HEIGHT_ARROW/2;
175 if (direction == RIGHT_ARROW)
176 arrow_point[1].x = x+WIDTH_ARROW;
178 arrow_point[1].x = x-WIDTH_ARROW;
179 arrow_point[1].y = y;
180 arrow_point[2].x = x;
181 arrow_point[2].y = y+HEIGHT_ARROW/2;;
183 gdk_draw_polygon(pixmap, gc, TRUE,
188 #define MAX_COMMENT 60
189 #define ITEM_HEIGHT 20
190 #define NODE_WIDTH 100
191 #define TOP_Y_BORDER 40
192 #define BOTTOM_Y_BORDER 0
193 #define COMMENT_WIDTH 250
195 /****************************************************************************/
196 static void dialog_graph_draw(graph_analysis_data_t* user_data)
198 guint32 i, last_item, first_item, last_node, first_node, display_items, display_nodes;
199 guint32 start_arrow, end_arrow, label_x, src_port_x, dst_port_x, arrow_width;
200 guint32 current_item;
201 guint32 left_x_border;
202 guint32 right_x_border;
203 guint32 top_y_border;
204 guint32 bottom_y_border;
205 graph_analysis_item_t *gai;
206 gboolean display_label;
208 #if GTK_MAJOR_VERSION < 2
211 FONT_TYPE *small_font;
214 PangoLayout *big_layout;
215 PangoLayout *small_layout;
217 guint32 label_width, label_height;
218 guint32 draw_width, draw_height;
219 char label_string[MAX_COMMENT];
224 #if GTK_MAJOR_VERSION <2
225 font = user_data->dlg.draw_area->style->font;
226 big_font = gdk_font_load("-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1");
227 small_font = gdk_font_load("-adobe-helvetica-bold-r-normal--10-120-75-75-p-70-iso8859-1");
229 if(!user_data->dlg.needs_redraw){
232 user_data->dlg.needs_redraw=FALSE;
237 gdk_draw_rectangle(user_data->dlg.pixmap,
238 user_data->dlg.draw_area->style->white_gc,
241 user_data->dlg.draw_area->allocation.width,
242 user_data->dlg.draw_area->allocation.height);
244 /* Calculate the y border */
245 top_y_border=TOP_Y_BORDER; /* to display the node IP address */
246 bottom_y_border=BOTTOM_Y_BORDER;
248 draw_height=user_data->dlg.pixmap_height-top_y_border-bottom_y_border;
250 first_item = user_data->dlg.first_item;
251 display_items = draw_height/ITEM_HEIGHT;
252 last_item = first_item+display_items-1;
254 /* get the items to display and fill the matrix array */
255 list = g_list_first(user_data->graph_info->list);
262 if (current_item>=display_items) break; /* the item is outside the display */
264 user_data->dlg.items[current_item].frame_num = gai->frame_num;
265 user_data->dlg.items[current_item].time = gai->time;
266 user_data->dlg.items[current_item].port_src = gai->port_src;
267 user_data->dlg.items[current_item].port_dst = gai->port_dst;
268 /* Add "..." if the length is 50 characters */
269 if (strlen(gai->frame_label) > 48) {
270 gai->frame_label[48] = '.';
271 gai->frame_label[47] = '.';
272 gai->frame_label[46] = '.';
274 user_data->dlg.items[current_item].frame_label = gai->frame_label;
275 user_data->dlg.items[current_item].comment = gai->comment;
276 user_data->dlg.items[current_item].conv_num = gai->conv_num;
277 user_data->dlg.items[current_item].src_node = gai->src_node;
278 user_data->dlg.items[current_item].dst_node = gai->dst_node;
279 user_data->dlg.items[current_item].line_style = gai->line_style;
285 list = g_list_next(list);
287 /* in case the windows is resized so we have to move the top item */
288 if ((first_item + display_items) > user_data->num_items){
289 if (display_items>user_data->num_items)
292 first_item = user_data->num_items - display_items;
295 /* in case there are less items than possible displayed */
296 display_items = current_item;
297 last_item = first_item+display_items-1;
299 /* if not items to display */
300 if (display_items == 0) return;
303 /* Calculate the x borders */
304 /* We use time from the last display item to calcultate the x left border */
305 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[display_items-1].time);
306 #if GTK_MAJOR_VERSION < 2
307 label_width=gdk_string_width(font, label_string);
308 label_height=gdk_string_height(font, label_string);
310 layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
311 big_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
312 small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
314 pango_layout_set_font_description(big_layout, pango_font_description_from_string("Helvetica-Bold 8"));
315 pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica-Bold 7"));
317 pango_layout_get_pixel_size(layout, &label_width, &label_height);
319 left_x_border=label_width+10;
320 user_data->dlg.left_x_border = left_x_border;
322 right_x_border=COMMENT_WIDTH;
324 /* Calculate the number of nodes to display */
325 draw_width=user_data->dlg.pixmap_width-right_x_border-left_x_border;
326 display_nodes = draw_width/NODE_WIDTH;
327 first_node = user_data->dlg.first_node;
329 /* in case the windows is resized so we have to move the left node */
330 if ((first_node + display_nodes) > user_data->num_nodes){
331 if (display_nodes>user_data->num_nodes)
334 first_node=user_data->num_nodes - display_nodes;
337 /* in case there are less nodes than possible displayed */
338 if (display_nodes>user_data->num_nodes) display_nodes=user_data->num_nodes;
340 last_node = first_node + display_nodes-1;
342 /* Paint the background items */
343 for (current_item=0; current_item<display_items; current_item++){
344 /* Paint background */
345 gdk_draw_rectangle(user_data->dlg.pixmap,
346 user_data->dlg.bg_gc[user_data->dlg.items[current_item].conv_num%MAX_NUM_COL_CONV],
349 top_y_border+current_item*ITEM_HEIGHT,
355 /* Draw the node names on top and the division lines */
356 for (i=0; i<display_nodes; i++){
357 /* draw the node IPs */
358 g_snprintf(label_string, MAX_LABEL, "%s",
359 ip_to_str((guint8 *)&(user_data->nodes[i+first_node])));
360 #if GTK_MAJOR_VERSION < 2
361 label_width=gdk_string_width(font, label_string);
362 label_height=gdk_string_height(font, label_string);
363 gdk_draw_string(user_data->dlg.pixmap,
365 user_data->dlg.draw_area->style->black_gc,
366 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
367 top_y_border/2-label_height/2,
370 pango_layout_set_text(layout, label_string, -1);
371 pango_layout_get_pixel_size(layout, &label_width, &label_height);
372 gdk_draw_layout(user_data->dlg.pixmap,
373 user_data->dlg.draw_area->style->black_gc,
374 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
375 top_y_border/2-label_height/2,
379 /* draw the node division lines */
380 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.div_line_gc,
381 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
383 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
384 user_data->dlg.pixmap_height-bottom_y_border);
393 for (current_item=0; current_item<display_items; current_item++){
395 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[current_item].time);
396 #if GTK_MAJOR_VERSION < 2
397 label_width=gdk_string_width(font, label_string);
398 label_height=gdk_string_height(font, label_string);
399 gdk_draw_string(user_data->dlg.pixmap,
401 user_data->dlg.draw_area->style->black_gc,
402 left_x_border-label_width-4,
403 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
406 pango_layout_set_text(layout, label_string, -1);
407 pango_layout_get_pixel_size(layout, &label_width, &label_height);
408 gdk_draw_layout(user_data->dlg.pixmap,
409 user_data->dlg.draw_area->style->black_gc,
410 left_x_border-label_width-4,
411 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
415 /*draw the comments */
416 g_snprintf(label_string, MAX_COMMENT, "%s", user_data->dlg.items[current_item].comment);
417 #if GTK_MAJOR_VERSION < 2
418 label_width=gdk_string_width(small_font, label_string);
419 label_height=gdk_string_height(small_font, label_string);
420 gdk_draw_string(user_data->dlg.pixmap,
422 user_data->dlg.draw_area->style->black_gc,
423 user_data->dlg.pixmap_width-right_x_border+3,
424 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
427 pango_layout_set_text(small_layout, label_string, -1);
428 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
429 gdk_draw_layout(user_data->dlg.pixmap,
430 user_data->dlg.draw_area->style->black_gc,
431 user_data->dlg.pixmap_width-right_x_border+3,
432 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
436 /* draw the arrow an frame label*/
437 display_label = FALSE;
438 if (user_data->dlg.items[current_item].src_node>=first_node){
439 if (user_data->dlg.items[current_item].src_node<=last_node){
440 start_arrow = left_x_border+(user_data->dlg.items[current_item].src_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
441 display_label = TRUE;
443 start_arrow = user_data->dlg.pixmap_width - right_x_border;
446 start_arrow = left_x_border;
449 if (user_data->dlg.items[current_item].dst_node>=first_node){
450 if (user_data->dlg.items[current_item].dst_node<=last_node){
451 end_arrow = left_x_border+(user_data->dlg.items[current_item].dst_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
452 display_label = TRUE;
454 end_arrow = user_data->dlg.pixmap_width - right_x_border;
457 end_arrow = left_x_border;
460 if (start_arrow != end_arrow){
461 /* draw the arrow line */
462 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
464 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7,
466 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7);
468 /* draw the additional line when line style is 2 pixels width */
469 if (user_data->dlg.items[current_item].line_style == 2){
470 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
472 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6,
474 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6);
478 if (start_arrow<end_arrow)
479 draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow-WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, RIGHT_ARROW);
481 draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow+WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, LEFT_ARROW);
484 /* draw the frame comment */
486 g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].frame_label);
487 #if GTK_MAJOR_VERSION < 2
488 label_width=gdk_string_width(big_font, label_string);
489 label_height=gdk_string_height(big_font, label_string);
491 pango_layout_set_text(big_layout, label_string, -1);
492 pango_layout_get_pixel_size(big_layout, &label_width, &label_height);
495 if (start_arrow<end_arrow){
496 arrow_width = end_arrow-start_arrow;
497 label_x = arrow_width/2+start_arrow;
500 arrow_width = start_arrow-end_arrow;
501 label_x = arrow_width/2+end_arrow;
504 if (label_width>arrow_width) arrow_width = label_width;
506 if (left_x_border > (label_x-label_width/2)) label_x = left_x_border + label_width/2;
508 if ((user_data->dlg.pixmap_width - right_x_border) < (label_x+label_width/2)) label_x = user_data->dlg.pixmap_width - right_x_border - label_width/2;
510 #if GTK_MAJOR_VERSION < 2
511 gdk_draw_string(user_data->dlg.pixmap,
513 user_data->dlg.draw_area->style->black_gc,
514 label_x - label_width/2,
515 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4-3,
518 gdk_draw_layout(user_data->dlg.pixmap,
519 user_data->dlg.draw_area->style->black_gc,
520 label_x - label_width/2,
521 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2-3,
525 /* draw the source port number */
526 if ((start_arrow != left_x_border) && (start_arrow != (user_data->dlg.pixmap_width - right_x_border))){
527 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_src);
528 #if GTK_MAJOR_VERSION < 2
529 label_width=gdk_string_width(small_font, label_string);
530 label_height=gdk_string_height(small_font, label_string);
532 pango_layout_set_text(small_layout, label_string, -1);
533 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
535 if (start_arrow<end_arrow){
536 src_port_x = start_arrow - label_width - 2;
539 src_port_x = start_arrow + 2;
541 #if GTK_MAJOR_VERSION < 2
542 gdk_draw_string(user_data->dlg.pixmap,
544 user_data->dlg.div_line_gc,
546 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
549 gdk_draw_layout(user_data->dlg.pixmap,
550 user_data->dlg.div_line_gc,
552 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
557 /* draw the destination port number */
558 if ((end_arrow != left_x_border) && (end_arrow != (user_data->dlg.pixmap_width - right_x_border))){
559 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_dst);
560 #if GTK_MAJOR_VERSION < 2
561 label_width=gdk_string_width(small_font, label_string);
562 label_height=gdk_string_height(small_font, label_string);
564 pango_layout_set_text(small_layout, label_string, -1);
565 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
567 if (start_arrow<end_arrow){
568 dst_port_x = end_arrow + 2;
571 dst_port_x = end_arrow - label_width - 2;
573 #if GTK_MAJOR_VERSION < 2
574 gdk_draw_string(user_data->dlg.pixmap,
576 user_data->dlg.div_line_gc,
578 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
581 gdk_draw_layout(user_data->dlg.pixmap,
582 user_data->dlg.div_line_gc,
584 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
592 #if GTK_MAJOR_VERSION >= 2
593 g_object_unref(G_OBJECT(layout));
596 /* draw the border on the selected item */
597 if ( (user_data->dlg.selected_item != 0xFFFFFFFF) && ( (user_data->dlg.selected_item>=first_item) && (user_data->dlg.selected_item<=last_item) )){
598 gdk_draw_rectangle(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
601 (user_data->dlg.selected_item-first_item)*ITEM_HEIGHT+TOP_Y_BORDER,
602 user_data->dlg.pixmap_width-COMMENT_WIDTH-left_x_border+1,
608 gdk_draw_pixmap(user_data->dlg.draw_area->window,
609 user_data->dlg.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.draw_area)],
610 user_data->dlg.pixmap,
613 user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
616 /* update the h_scrollbar */
617 user_data->dlg.h_scrollbar_adjustment->upper=(gfloat) user_data->num_nodes-1;
618 user_data->dlg.h_scrollbar_adjustment->step_increment=1;
619 user_data->dlg.h_scrollbar_adjustment->page_increment=(gfloat) (last_node-first_node);
620 user_data->dlg.h_scrollbar_adjustment->page_size=(gfloat) (last_node-first_node);
621 user_data->dlg.h_scrollbar_adjustment->value=(gfloat) first_node;
623 gtk_adjustment_changed(user_data->dlg.h_scrollbar_adjustment);
624 gtk_adjustment_value_changed(user_data->dlg.h_scrollbar_adjustment);
626 /* update the v_scrollbar */
627 user_data->dlg.v_scrollbar_adjustment->upper=(gfloat) user_data->num_items-1;
628 user_data->dlg.v_scrollbar_adjustment->step_increment=1;
629 user_data->dlg.v_scrollbar_adjustment->page_increment=(gfloat) (last_item-first_item);
630 user_data->dlg.v_scrollbar_adjustment->page_size=(gfloat) (last_item-first_item);
631 user_data->dlg.v_scrollbar_adjustment->value=(gfloat) first_item;
633 gtk_adjustment_changed(user_data->dlg.v_scrollbar_adjustment);
634 gtk_adjustment_value_changed(user_data->dlg.v_scrollbar_adjustment);
638 /****************************************************************************/
639 static void dialog_graph_redraw(graph_analysis_data_t* user_data)
641 user_data->dlg.needs_redraw=TRUE;
642 dialog_graph_draw(user_data);
645 /****************************************************************************/
646 static gint quit(GtkWidget *widget, GdkEventExpose *event _U_)
648 graph_analysis_data_t *user_data;
650 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
652 user_data->dlg.window = NULL;
658 /****************************************************************************/
659 static gint button_press_event(GtkWidget *widget, GdkEventButton *event _U_)
661 graph_analysis_data_t *user_data;
664 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
666 if (event->type != GDK_BUTTON_PRESS) return TRUE;
668 if (event->y<TOP_Y_BORDER) return TRUE;
670 /* get the item clicked */
671 item = ((guint32)event->y - TOP_Y_BORDER) / ITEM_HEIGHT;
672 user_data->dlg.selected_item = item + user_data->dlg.first_item;
674 user_data->dlg.needs_redraw=TRUE;
675 dialog_graph_draw(user_data);
677 goto_frame(&cfile, user_data->dlg.items[item].frame_num);
682 /****************************************************************************/
683 static gint expose_event(GtkWidget *widget, GdkEventExpose *event)
685 graph_analysis_data_t *user_data;
687 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
693 gdk_draw_pixmap(widget->window,
694 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
695 user_data->dlg.pixmap,
696 event->area.x, event->area.y,
697 event->area.x, event->area.y,
698 event->area.width, event->area.height);
703 static const GdkColor COLOR_GRAY = {0, 0x7fff, 0x7fff, 0x7fff};
705 /****************************************************************************/
706 static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
708 graph_analysis_data_t *user_data;
710 GdkColor color_div_line = COLOR_GRAY;
712 static GdkColor col[MAX_NUM_COL_CONV] = {
713 {0, 0x00FF, 0xFFFF, 0x00FF},
714 {0, 0xFFFF, 0xFFFF, 0x00FF},
715 {0, 0xFFFF, 0x00FF, 0x00FF},
716 {0, 0xFFFF, 0x00FF, 0xFFFF},
717 {0, 0x00FF, 0x00FF, 0xFFFF},
718 {0, 0x00FF, 0xFFFF, 0xFFFF},
719 {0, 0xFFFF, 0x80FF, 0x00FF},
720 {0, 0x80FF, 0x00FF, 0xFFFF},
721 {0, 0x00FF, 0x80FF, 0xFFFF},
722 {0, 0xFFFF, 0x00FF, 0x80FF}
725 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
731 if(user_data->dlg.pixmap){
732 gdk_pixmap_unref(user_data->dlg.pixmap);
733 user_data->dlg.pixmap=NULL;
736 user_data->dlg.pixmap=gdk_pixmap_new(widget->window,
737 widget->allocation.width,
738 widget->allocation.height,
740 user_data->dlg.pixmap_width=widget->allocation.width;
741 user_data->dlg.pixmap_height=widget->allocation.height;
743 gdk_draw_rectangle(user_data->dlg.pixmap,
744 widget->style->white_gc,
747 widget->allocation.width,
748 widget->allocation.height);
750 /* create gc for division lines and set the line stype to dash*/
751 user_data->dlg.div_line_gc=gdk_gc_new(user_data->dlg.pixmap);
752 gdk_gc_set_line_attributes(user_data->dlg.div_line_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0);
753 #if GTK_MAJOR_VERSION < 2
754 colormap = gtk_widget_get_colormap (widget);
755 if (!gdk_color_alloc (colormap, &color_div_line)){
756 g_warning ("Couldn't allocate color");
758 gdk_gc_set_foreground(user_data->dlg.div_line_gc, &color_div_line);
760 gdk_gc_set_rgb_fg_color(user_data->dlg.div_line_gc, &color_div_line);
763 /* create gcs for the background items */
765 for (i=0; i<MAX_NUM_COL_CONV; i++){
766 user_data->dlg.bg_gc[i]=gdk_gc_new(user_data->dlg.pixmap);
767 #if GTK_MAJOR_VERSION < 2
768 colormap = gtk_widget_get_colormap (widget);
769 if (!gdk_color_alloc (colormap, &col[i])){
770 g_warning ("Couldn't allocate color");
772 gdk_gc_set_foreground(user_data->dlg.bg_gc[i], &col[i]);
774 gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]);
778 dialog_graph_redraw(user_data);
782 /****************************************************************************/
783 static gint h_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
785 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
787 if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes)
788 && (user_data->dlg.h_scrollbar_adjustment->value >= user_data->dlg.first_node ))
791 if (user_data->dlg.first_node == (guint16) user_data->dlg.h_scrollbar_adjustment->value)
794 user_data->dlg.first_node = (guint16) user_data->dlg.h_scrollbar_adjustment->value;
796 dialog_graph_redraw(user_data);
800 /****************************************************************************/
801 static gint v_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
803 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
804 if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items)
805 && (user_data->dlg.v_scrollbar_adjustment->value >= user_data->dlg.first_item ))
808 if (user_data->dlg.first_item == user_data->dlg.v_scrollbar_adjustment->value)
811 user_data->dlg.first_item = (guint32) user_data->dlg.v_scrollbar_adjustment->value;
813 dialog_graph_redraw(user_data);
817 /****************************************************************************/
818 static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box)
823 hbox=gtk_hbox_new(FALSE, 0);
824 gtk_widget_show(hbox);
826 vbox=gtk_vbox_new(FALSE, 0);
827 gtk_widget_show(vbox);
830 user_data->dlg.draw_area=gtk_drawing_area_new();
831 SIGNAL_CONNECT(user_data->dlg.draw_area, "destroy", quit, user_data);
832 OBJECT_SET_DATA(user_data->dlg.draw_area, "graph_analysis_data_t", user_data);
834 WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
836 /* signals needed to handle backing pixmap */
837 SIGNAL_CONNECT(user_data->dlg.draw_area, "expose_event", expose_event, NULL);
838 SIGNAL_CONNECT(user_data->dlg.draw_area, "configure_event", configure_event, user_data);
840 gtk_widget_add_events (user_data->dlg.draw_area,
841 GDK_BUTTON_PRESS_MASK);
842 SIGNAL_CONNECT(user_data->dlg.draw_area, "button_press_event", button_press_event, user_data);
844 gtk_widget_show(user_data->dlg.draw_area);
845 gtk_box_pack_start(GTK_BOX(vbox), user_data->dlg.draw_area, TRUE, TRUE, 0);
847 /* create the associated h_scrollbar */
848 user_data->dlg.h_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
849 user_data->dlg.h_scrollbar=gtk_hscrollbar_new(user_data->dlg.h_scrollbar_adjustment);
850 gtk_widget_show(user_data->dlg.h_scrollbar);
851 gtk_box_pack_end(GTK_BOX(vbox), user_data->dlg.h_scrollbar, FALSE, FALSE, 0);
852 SIGNAL_CONNECT(user_data->dlg.h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, user_data);
854 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
856 /* create the associated v_scrollbar */
857 user_data->dlg.v_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
858 user_data->dlg.v_scrollbar=gtk_vscrollbar_new(user_data->dlg.v_scrollbar_adjustment);
859 gtk_widget_show(user_data->dlg.v_scrollbar);
860 gtk_box_pack_end(GTK_BOX(hbox), user_data->dlg.v_scrollbar, FALSE, FALSE, 0);
861 SIGNAL_CONNECT(user_data->dlg.v_scrollbar_adjustment, "value_changed", v_scrollbar_changed, user_data);
863 gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
867 /****************************************************************************/
868 static void dialog_graph_create_window(graph_analysis_data_t* user_data)
873 GtkWidget *label = NULL;
875 /* create the main window */
876 user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
879 vbox=gtk_vbox_new(FALSE, 0);
880 gtk_container_add(GTK_CONTAINER(user_data->dlg.window), vbox);
881 gtk_widget_show(vbox);
883 create_draw_area(user_data, vbox);
885 hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
886 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
887 gtk_widget_show(hbox);
889 bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
890 window_set_cancel_button(user_data->dlg.window, bt_close, window_cancel_button_cb);
892 SIGNAL_CONNECT(user_data->dlg.window, "delete_event", window_delete_event_cb, NULL);
894 gtk_widget_show(user_data->dlg.window);
895 window_present(user_data->dlg.window);
898 /* Return the index array if the node is in the array. Return -1 if there is room in the array
899 * and Return -2 if the array is full
901 /****************************************************************************/
902 gint is_node_array(graph_analysis_data_t* user_data, guint32 node)
905 for (i=0; i<MAX_NUM_NODES; i++){
906 if (user_data->nodes[i] == 0) return -1; /* it is not in the array */
907 if (user_data->nodes[i] == node) return i; /* it is in the array */
909 return -2; /* array full */
913 /* Get the nodes (IPs) from the list */
914 /****************************************************************************/
915 void get_nodes(graph_analysis_data_t* user_data)
918 graph_analysis_item_t *gai;
921 /* fill the node array */
922 list = g_list_first(user_data->graph_info->list);
927 user_data->num_items++;
928 /* check source IP node */
929 index = is_node_array(user_data, gai->ip_src);
931 case -2: /* array full */
932 gai->src_node = NODE_OVERFLOW;
934 case -1: /* not in array */
935 user_data->nodes[user_data->num_nodes] = gai->ip_src;
936 gai->src_node = user_data->num_nodes;
937 user_data->num_nodes++;
939 default: /* it is in the array, just update the src_node */
940 gai->src_node = (guint16)index;
943 /* check destination IP node */
944 index = is_node_array(user_data, gai->ip_dst);
946 case -2: /* array full */
947 gai->dst_node = NODE_OVERFLOW;
949 case -1: /* not in array */
950 user_data->nodes[user_data->num_nodes] = gai->ip_dst;
951 gai->dst_node = user_data->num_nodes;
952 user_data->num_nodes++;
954 default: /* it is in the array, just update the dst_node */
955 gai->dst_node = (guint16)index;
959 list = g_list_next(list);
963 /****************************************************************************/
964 /* XXX only handles IPv4, should add IPv6 support */
965 graph_analysis_data_t* graph_analysis_init()
967 graph_analysis_data_t* user_data;
969 user_data = g_malloc(sizeof(graph_analysis_data_t));
972 graph_analysis_init_dlg(user_data);
977 /****************************************************************************/
978 void graph_analysis_create(graph_analysis_data_t* user_data)
981 graph_analysis_reset(user_data);
983 /* get nodes (each node is an IP address) */
984 get_nodes(user_data);
986 /* create the graph windows */
987 dialog_graph_create_window(user_data);
989 /* redraw the graph */
990 dialog_graph_redraw(user_data);
995 /****************************************************************************/
996 void graph_analysis_update(graph_analysis_data_t* user_data)
999 graph_analysis_reset(user_data);
1001 /* get nodes (each node is an IP address) */
1002 get_nodes(user_data);
1004 /* redraw the graph */
1005 dialog_graph_redraw(user_data);
1007 window_present(user_data->dlg.window);