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>
41 #include "gtkglobals.h"
43 #include "dlg_utils.h"
46 #include "compat_macros.h"
53 /****************************************************************************/
56 #define OK_TEXT "[ Ok ]"
57 #define PT_UNDEFINED -1
60 #if GTK_MAJOR_VERSION < 2
62 GdkColormap *colormap;
65 /****************************************************************************/
66 /* Reset the user_data structure */
67 static void graph_analysis_reset(graph_analysis_data_t* user_data)
71 user_data->num_nodes = 0;
72 user_data->num_items = 0;
73 for (i=0; i<MAX_NUM_NODES; i++){
74 user_data->nodes[i] = 0;
77 user_data->dlg.first_node=0;
78 user_data->dlg.first_item=0;
79 user_data->dlg.left_x_border=0;
80 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
83 /****************************************************************************/
84 /* Reset the user_data structure */
85 static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
87 /* init dialog_graph */
88 user_data->dlg.needs_redraw=TRUE;
89 user_data->dlg.draw_area=NULL;
90 user_data->dlg.pixmap=NULL;
91 user_data->dlg.h_scrollbar=NULL;
92 user_data->dlg.h_scrollbar_adjustment=NULL;
93 user_data->dlg.v_scrollbar=NULL;
94 user_data->dlg.v_scrollbar_adjustment=NULL;
95 user_data->dlg.pixmap_width=600;
96 user_data->dlg.pixmap_height=400;
97 user_data->dlg.first_node=0;
98 user_data->dlg.first_item=0;
99 user_data->dlg.left_x_border=0;
100 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
101 user_data->dlg.window=NULL;
104 /****************************************************************************/
108 /****************************************************************************/
109 /* close the dialog window and remove the tap listener */
110 static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
117 /****************************************************************************/
118 static void dialog_graph_set_title(graph_analysis_data_t* user_data)
121 if (!user_data->dlg.window){
124 title = g_strdup_printf("Ale");
126 gtk_window_set_title(GTK_WINDOW(user_data->dlg.window), title);
130 #define RIGHT_ARROW 1
132 #define WIDTH_ARROW 8
133 #define HEIGHT_ARROW 6
135 /****************************************************************************/
136 static void draw_arrow(GdkDrawable *pixmap, GdkGC *gc, gint x, gint y, gboolean direction)
138 GdkPoint arrow_point[3];
140 arrow_point[0].x = x;
141 arrow_point[0].y = y-HEIGHT_ARROW/2;
142 if (direction == RIGHT_ARROW)
143 arrow_point[1].x = x+WIDTH_ARROW;
145 arrow_point[1].x = x-WIDTH_ARROW;
146 arrow_point[1].y = y;
147 arrow_point[2].x = x;
148 arrow_point[2].y = y+HEIGHT_ARROW/2;;
150 gdk_draw_polygon(pixmap, gc, TRUE,
155 #define MAX_COMMENT 60
156 #define ITEM_HEIGHT 20
157 #define NODE_WIDTH 100
158 #define TOP_Y_BORDER 40
159 #define BOTTOM_Y_BORDER 0
160 #define COMMENT_WIDTH 250
162 /****************************************************************************/
163 static void dialog_graph_draw(graph_analysis_data_t* user_data)
165 guint32 i, last_item, first_item, last_node, first_node, display_items, display_nodes;
166 guint32 start_arrow, end_arrow, label_x, src_port_x, dst_port_x, arrow_width;
167 guint32 current_item;
168 guint32 left_x_border;
169 guint32 right_x_border;
170 guint32 top_y_border;
171 guint32 bottom_y_border;
172 graph_analysis_item_t *gai;
173 gboolean display_label;
175 #if GTK_MAJOR_VERSION < 2
178 FONT_TYPE *small_font;
181 PangoLayout *big_layout;
182 PangoLayout *small_layout;
184 guint32 label_width, label_height;
185 guint32 draw_width, draw_height;
186 char label_string[MAX_COMMENT];
191 #if GTK_MAJOR_VERSION <2
192 font = user_data->dlg.draw_area->style->font;
193 big_font = gdk_font_load("-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1");
194 small_font = gdk_font_load("-adobe-helvetica-bold-r-normal--10-120-75-75-p-70-iso8859-1");
196 if(!user_data->dlg.needs_redraw){
199 user_data->dlg.needs_redraw=FALSE;
204 gdk_draw_rectangle(user_data->dlg.pixmap,
205 user_data->dlg.draw_area->style->white_gc,
208 user_data->dlg.draw_area->allocation.width,
209 user_data->dlg.draw_area->allocation.height);
211 /* Calculate the y border */
212 top_y_border=TOP_Y_BORDER; /* to display the node IP address */
213 bottom_y_border=BOTTOM_Y_BORDER;
215 draw_height=user_data->dlg.pixmap_height-top_y_border-bottom_y_border;
217 first_item = user_data->dlg.first_item;
218 display_items = draw_height/ITEM_HEIGHT;
219 last_item = first_item+display_items-1;
221 /* get the items to display and fill the matrix array */
222 list = g_list_first(user_data->graph_info->list);
229 if (current_item>=display_items) break; /* the item is outside the display */
231 user_data->dlg.items[current_item].frame_num = gai->frame_num;
232 user_data->dlg.items[current_item].time = gai->time;
233 user_data->dlg.items[current_item].port_src = gai->port_src;
234 user_data->dlg.items[current_item].port_dst = gai->port_dst;
235 /* Add "..." if the length is 50 characters */
236 if (strlen(gai->frame_label) > 48) {
237 gai->frame_label[48] = '.';
238 gai->frame_label[47] = '.';
239 gai->frame_label[46] = '.';
241 user_data->dlg.items[current_item].frame_label = gai->frame_label;
242 user_data->dlg.items[current_item].comment = gai->comment;
243 user_data->dlg.items[current_item].conv_num = gai->conv_num;
244 user_data->dlg.items[current_item].src_node = gai->src_node;
245 user_data->dlg.items[current_item].dst_node = gai->dst_node;
246 user_data->dlg.items[current_item].line_style = gai->line_style;
252 list = g_list_next(list);
254 /* in case the windows is resized so we have to move the top item */
255 if ((first_item + display_items) > user_data->num_items){
256 if (display_items>user_data->num_items)
259 first_item = user_data->num_items - display_items;
262 /* in case there are less items than possible displayed */
263 display_items = current_item;
264 last_item = first_item+display_items-1;
266 /* if not items to display */
267 if (display_items == 0) return;
270 /* Calculate the x borders */
271 /* We use time from the last display item to calcultate the x left border */
272 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[display_items-1].time);
273 #if GTK_MAJOR_VERSION < 2
274 label_width=gdk_string_width(font, label_string);
275 label_height=gdk_string_height(font, label_string);
277 layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
278 big_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
279 small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
281 pango_layout_set_font_description(big_layout, pango_font_description_from_string("Helvetica-Bold 8"));
282 pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica-Bold 7"));
284 pango_layout_get_pixel_size(layout, &label_width, &label_height);
286 left_x_border=label_width+10;
287 user_data->dlg.left_x_border = left_x_border;
289 right_x_border=COMMENT_WIDTH;
291 /* Calculate the number of nodes to display */
292 draw_width=user_data->dlg.pixmap_width-right_x_border-left_x_border;
293 display_nodes = draw_width/NODE_WIDTH;
294 first_node = user_data->dlg.first_node;
296 /* in case the windows is resized so we have to move the left node */
297 if ((first_node + display_nodes) > user_data->num_nodes){
298 if (display_nodes>user_data->num_nodes)
301 first_node=user_data->num_nodes - display_nodes;
304 /* in case there are less nodes than possible displayed */
305 if (display_nodes>user_data->num_nodes) display_nodes=user_data->num_nodes;
307 last_node = first_node + display_nodes-1;
309 /* Paint the background items */
310 for (current_item=0; current_item<display_items; current_item++){
311 /* Paint background */
312 gdk_draw_rectangle(user_data->dlg.pixmap,
313 user_data->dlg.bg_gc[user_data->dlg.items[current_item].conv_num%MAX_NUM_COL_CONV],
316 top_y_border+current_item*ITEM_HEIGHT,
322 /* Draw the node names on top and the division lines */
323 for (i=0; i<display_nodes; i++){
324 /* draw the node IPs */
325 g_snprintf(label_string, MAX_LABEL, "%s",
326 ip_to_str((guint8 *)&(user_data->nodes[i+first_node])));
327 #if GTK_MAJOR_VERSION < 2
328 label_width=gdk_string_width(font, label_string);
329 label_height=gdk_string_height(font, label_string);
330 gdk_draw_string(user_data->dlg.pixmap,
332 user_data->dlg.draw_area->style->black_gc,
333 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
334 top_y_border/2-label_height/2,
337 pango_layout_set_text(layout, label_string, -1);
338 pango_layout_get_pixel_size(layout, &label_width, &label_height);
339 gdk_draw_layout(user_data->dlg.pixmap,
340 user_data->dlg.draw_area->style->black_gc,
341 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
342 top_y_border/2-label_height/2,
346 /* draw the node division lines */
347 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.div_line_gc,
348 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
350 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
351 user_data->dlg.pixmap_height-bottom_y_border);
360 for (current_item=0; current_item<display_items; current_item++){
362 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[current_item].time);
363 #if GTK_MAJOR_VERSION < 2
364 label_width=gdk_string_width(font, label_string);
365 label_height=gdk_string_height(font, label_string);
366 gdk_draw_string(user_data->dlg.pixmap,
368 user_data->dlg.draw_area->style->black_gc,
369 left_x_border-label_width-4,
370 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
373 pango_layout_set_text(layout, label_string, -1);
374 pango_layout_get_pixel_size(layout, &label_width, &label_height);
375 gdk_draw_layout(user_data->dlg.pixmap,
376 user_data->dlg.draw_area->style->black_gc,
377 left_x_border-label_width-4,
378 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
382 /*draw the comments */
383 g_snprintf(label_string, MAX_COMMENT, "%s", user_data->dlg.items[current_item].comment);
384 #if GTK_MAJOR_VERSION < 2
385 label_width=gdk_string_width(small_font, label_string);
386 label_height=gdk_string_height(small_font, label_string);
387 gdk_draw_string(user_data->dlg.pixmap,
389 user_data->dlg.draw_area->style->black_gc,
390 user_data->dlg.pixmap_width-right_x_border+3,
391 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
394 pango_layout_set_text(small_layout, label_string, -1);
395 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
396 gdk_draw_layout(user_data->dlg.pixmap,
397 user_data->dlg.draw_area->style->black_gc,
398 user_data->dlg.pixmap_width-right_x_border+3,
399 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
403 /* draw the arrow an frame label*/
404 display_label = FALSE;
405 if (user_data->dlg.items[current_item].src_node>=first_node){
406 if (user_data->dlg.items[current_item].src_node<=last_node){
407 start_arrow = left_x_border+(user_data->dlg.items[current_item].src_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
408 display_label = TRUE;
410 start_arrow = user_data->dlg.pixmap_width - right_x_border;
413 start_arrow = left_x_border;
416 if (user_data->dlg.items[current_item].dst_node>=first_node){
417 if (user_data->dlg.items[current_item].dst_node<=last_node){
418 end_arrow = left_x_border+(user_data->dlg.items[current_item].dst_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
419 display_label = TRUE;
421 end_arrow = user_data->dlg.pixmap_width - right_x_border;
424 end_arrow = left_x_border;
427 if (start_arrow != end_arrow){
428 /* draw the arrow line */
429 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
431 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7,
433 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7);
435 /* draw the additional line when line style is 2 pixels width */
436 if (user_data->dlg.items[current_item].line_style == 2){
437 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
439 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6,
441 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6);
445 if (start_arrow<end_arrow)
446 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);
448 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);
451 /* draw the frame comment */
453 g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].frame_label);
454 #if GTK_MAJOR_VERSION < 2
455 label_width=gdk_string_width(big_font, label_string);
456 label_height=gdk_string_height(big_font, label_string);
458 pango_layout_set_text(big_layout, label_string, -1);
459 pango_layout_get_pixel_size(big_layout, &label_width, &label_height);
462 if (start_arrow<end_arrow){
463 arrow_width = end_arrow-start_arrow;
464 label_x = arrow_width/2+start_arrow;
467 arrow_width = start_arrow-end_arrow;
468 label_x = arrow_width/2+end_arrow;
471 if (label_width>arrow_width) arrow_width = label_width;
473 if (left_x_border > (label_x-label_width/2)) label_x = left_x_border + label_width/2;
475 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;
477 #if GTK_MAJOR_VERSION < 2
478 gdk_draw_string(user_data->dlg.pixmap,
480 user_data->dlg.draw_area->style->black_gc,
481 label_x - label_width/2,
482 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4-3,
485 gdk_draw_layout(user_data->dlg.pixmap,
486 user_data->dlg.draw_area->style->black_gc,
487 label_x - label_width/2,
488 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2-3,
492 /* draw the source port number */
493 if ((start_arrow != left_x_border) && (start_arrow != (user_data->dlg.pixmap_width - right_x_border))){
494 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_src);
495 #if GTK_MAJOR_VERSION < 2
496 label_width=gdk_string_width(small_font, label_string);
497 label_height=gdk_string_height(small_font, label_string);
499 pango_layout_set_text(small_layout, label_string, -1);
500 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
502 if (start_arrow<end_arrow){
503 src_port_x = start_arrow - label_width - 2;
506 src_port_x = start_arrow + 2;
508 #if GTK_MAJOR_VERSION < 2
509 gdk_draw_string(user_data->dlg.pixmap,
511 user_data->dlg.div_line_gc,
513 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
516 gdk_draw_layout(user_data->dlg.pixmap,
517 user_data->dlg.div_line_gc,
519 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
524 /* draw the destination port number */
525 if ((end_arrow != left_x_border) && (end_arrow != (user_data->dlg.pixmap_width - right_x_border))){
526 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_dst);
527 #if GTK_MAJOR_VERSION < 2
528 label_width=gdk_string_width(small_font, label_string);
529 label_height=gdk_string_height(small_font, label_string);
531 pango_layout_set_text(small_layout, label_string, -1);
532 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
534 if (start_arrow<end_arrow){
535 dst_port_x = end_arrow + 2;
538 dst_port_x = end_arrow - label_width - 2;
540 #if GTK_MAJOR_VERSION < 2
541 gdk_draw_string(user_data->dlg.pixmap,
543 user_data->dlg.div_line_gc,
545 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
548 gdk_draw_layout(user_data->dlg.pixmap,
549 user_data->dlg.div_line_gc,
551 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
559 #if GTK_MAJOR_VERSION >= 2
560 g_object_unref(G_OBJECT(layout));
563 /* draw the border on the selected item */
564 if ( (user_data->dlg.selected_item != 0xFFFFFFFF) && ( (user_data->dlg.selected_item>=first_item) && (user_data->dlg.selected_item<=last_item) )){
565 gdk_draw_rectangle(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
568 (user_data->dlg.selected_item-first_item)*ITEM_HEIGHT+TOP_Y_BORDER,
569 user_data->dlg.pixmap_width-COMMENT_WIDTH-left_x_border+1,
575 gdk_draw_pixmap(user_data->dlg.draw_area->window,
576 user_data->dlg.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.draw_area)],
577 user_data->dlg.pixmap,
580 user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
583 /* update the h_scrollbar */
584 user_data->dlg.h_scrollbar_adjustment->upper=(gfloat) user_data->num_nodes-1;
585 user_data->dlg.h_scrollbar_adjustment->step_increment=1;
586 user_data->dlg.h_scrollbar_adjustment->page_increment=(gfloat) (last_node-first_node);
587 user_data->dlg.h_scrollbar_adjustment->page_size=(gfloat) (last_node-first_node);
588 user_data->dlg.h_scrollbar_adjustment->value=(gfloat) first_node;
590 gtk_adjustment_changed(user_data->dlg.h_scrollbar_adjustment);
591 gtk_adjustment_value_changed(user_data->dlg.h_scrollbar_adjustment);
593 /* update the v_scrollbar */
594 user_data->dlg.v_scrollbar_adjustment->upper=(gfloat) user_data->num_items-1;
595 user_data->dlg.v_scrollbar_adjustment->step_increment=1;
596 user_data->dlg.v_scrollbar_adjustment->page_increment=(gfloat) (last_item-first_item);
597 user_data->dlg.v_scrollbar_adjustment->page_size=(gfloat) (last_item-first_item);
598 user_data->dlg.v_scrollbar_adjustment->value=(gfloat) first_item;
600 gtk_adjustment_changed(user_data->dlg.v_scrollbar_adjustment);
601 gtk_adjustment_value_changed(user_data->dlg.v_scrollbar_adjustment);
605 /****************************************************************************/
606 static void dialog_graph_redraw(graph_analysis_data_t* user_data)
608 user_data->dlg.needs_redraw=TRUE;
609 dialog_graph_draw(user_data);
612 /****************************************************************************/
613 static gint quit(GtkWidget *widget, GdkEventExpose *event _U_)
615 graph_analysis_data_t *user_data;
617 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
619 user_data->dlg.window = NULL;
625 /****************************************************************************/
626 static gint button_press_event(GtkWidget *widget, GdkEventButton *event _U_)
628 graph_analysis_data_t *user_data;
631 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
633 if (event->type != GDK_BUTTON_PRESS) return TRUE;
635 if (event->y<TOP_Y_BORDER) return TRUE;
637 /* get the item clicked */
638 item = ((guint32)event->y - TOP_Y_BORDER) / ITEM_HEIGHT;
639 user_data->dlg.selected_item = item + user_data->dlg.first_item;
641 user_data->dlg.needs_redraw=TRUE;
642 dialog_graph_draw(user_data);
644 cf_goto_frame(&cfile, user_data->dlg.items[item].frame_num);
649 /****************************************************************************/
650 static gint expose_event(GtkWidget *widget, GdkEventExpose *event)
652 graph_analysis_data_t *user_data;
654 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
660 gdk_draw_pixmap(widget->window,
661 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
662 user_data->dlg.pixmap,
663 event->area.x, event->area.y,
664 event->area.x, event->area.y,
665 event->area.width, event->area.height);
670 static const GdkColor COLOR_GRAY = {0, 0x7fff, 0x7fff, 0x7fff};
672 /****************************************************************************/
673 static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
675 graph_analysis_data_t *user_data;
677 GdkColor color_div_line = COLOR_GRAY;
679 static GdkColor col[MAX_NUM_COL_CONV] = {
680 {0, 0x00FF, 0xFFFF, 0x00FF},
681 {0, 0xFFFF, 0xFFFF, 0x00FF},
682 {0, 0xFFFF, 0x00FF, 0x00FF},
683 {0, 0xFFFF, 0x00FF, 0xFFFF},
684 {0, 0x00FF, 0x00FF, 0xFFFF},
685 {0, 0x00FF, 0xFFFF, 0xFFFF},
686 {0, 0xFFFF, 0x80FF, 0x00FF},
687 {0, 0x80FF, 0x00FF, 0xFFFF},
688 {0, 0x00FF, 0x80FF, 0xFFFF},
689 {0, 0xFFFF, 0x00FF, 0x80FF}
692 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
698 if(user_data->dlg.pixmap){
699 gdk_pixmap_unref(user_data->dlg.pixmap);
700 user_data->dlg.pixmap=NULL;
703 user_data->dlg.pixmap=gdk_pixmap_new(widget->window,
704 widget->allocation.width,
705 widget->allocation.height,
707 user_data->dlg.pixmap_width=widget->allocation.width;
708 user_data->dlg.pixmap_height=widget->allocation.height;
710 gdk_draw_rectangle(user_data->dlg.pixmap,
711 widget->style->white_gc,
714 widget->allocation.width,
715 widget->allocation.height);
717 /* create gc for division lines and set the line stype to dash*/
718 user_data->dlg.div_line_gc=gdk_gc_new(user_data->dlg.pixmap);
719 gdk_gc_set_line_attributes(user_data->dlg.div_line_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0);
720 #if GTK_MAJOR_VERSION < 2
721 colormap = gtk_widget_get_colormap (widget);
722 if (!gdk_color_alloc (colormap, &color_div_line)){
723 g_warning ("Couldn't allocate color");
725 gdk_gc_set_foreground(user_data->dlg.div_line_gc, &color_div_line);
727 gdk_gc_set_rgb_fg_color(user_data->dlg.div_line_gc, &color_div_line);
730 /* create gcs for the background items */
732 for (i=0; i<MAX_NUM_COL_CONV; i++){
733 user_data->dlg.bg_gc[i]=gdk_gc_new(user_data->dlg.pixmap);
734 #if GTK_MAJOR_VERSION < 2
735 colormap = gtk_widget_get_colormap (widget);
736 if (!gdk_color_alloc (colormap, &col[i])){
737 g_warning ("Couldn't allocate color");
739 gdk_gc_set_foreground(user_data->dlg.bg_gc[i], &col[i]);
741 gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]);
745 dialog_graph_redraw(user_data);
749 /****************************************************************************/
750 static gint h_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
752 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
754 if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes)
755 && (user_data->dlg.h_scrollbar_adjustment->value >= user_data->dlg.first_node ))
758 if (user_data->dlg.first_node == (guint16) user_data->dlg.h_scrollbar_adjustment->value)
761 user_data->dlg.first_node = (guint16) user_data->dlg.h_scrollbar_adjustment->value;
763 dialog_graph_redraw(user_data);
767 /****************************************************************************/
768 static gint v_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
770 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
771 if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items)
772 && (user_data->dlg.v_scrollbar_adjustment->value >= user_data->dlg.first_item ))
775 if (user_data->dlg.first_item == user_data->dlg.v_scrollbar_adjustment->value)
778 user_data->dlg.first_item = (guint32) user_data->dlg.v_scrollbar_adjustment->value;
780 dialog_graph_redraw(user_data);
784 /****************************************************************************/
785 static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box)
790 hbox=gtk_hbox_new(FALSE, 0);
791 gtk_widget_show(hbox);
793 vbox=gtk_vbox_new(FALSE, 0);
794 gtk_widget_show(vbox);
797 user_data->dlg.draw_area=gtk_drawing_area_new();
798 SIGNAL_CONNECT(user_data->dlg.draw_area, "destroy", quit, user_data);
799 OBJECT_SET_DATA(user_data->dlg.draw_area, "graph_analysis_data_t", user_data);
801 WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
803 /* signals needed to handle backing pixmap */
804 SIGNAL_CONNECT(user_data->dlg.draw_area, "expose_event", expose_event, NULL);
805 SIGNAL_CONNECT(user_data->dlg.draw_area, "configure_event", configure_event, user_data);
807 gtk_widget_add_events (user_data->dlg.draw_area,
808 GDK_BUTTON_PRESS_MASK);
809 SIGNAL_CONNECT(user_data->dlg.draw_area, "button_press_event", button_press_event, user_data);
811 gtk_widget_show(user_data->dlg.draw_area);
812 gtk_box_pack_start(GTK_BOX(vbox), user_data->dlg.draw_area, TRUE, TRUE, 0);
814 /* create the associated h_scrollbar */
815 user_data->dlg.h_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
816 user_data->dlg.h_scrollbar=gtk_hscrollbar_new(user_data->dlg.h_scrollbar_adjustment);
817 gtk_widget_show(user_data->dlg.h_scrollbar);
818 gtk_box_pack_end(GTK_BOX(vbox), user_data->dlg.h_scrollbar, FALSE, FALSE, 0);
819 SIGNAL_CONNECT(user_data->dlg.h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, user_data);
821 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
823 /* create the associated v_scrollbar */
824 user_data->dlg.v_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
825 user_data->dlg.v_scrollbar=gtk_vscrollbar_new(user_data->dlg.v_scrollbar_adjustment);
826 gtk_widget_show(user_data->dlg.v_scrollbar);
827 gtk_box_pack_end(GTK_BOX(hbox), user_data->dlg.v_scrollbar, FALSE, FALSE, 0);
828 SIGNAL_CONNECT(user_data->dlg.v_scrollbar_adjustment, "value_changed", v_scrollbar_changed, user_data);
830 gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
834 /****************************************************************************/
835 static void dialog_graph_create_window(graph_analysis_data_t* user_data)
841 /* create the main window */
842 user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
845 vbox=gtk_vbox_new(FALSE, 0);
846 gtk_container_add(GTK_CONTAINER(user_data->dlg.window), vbox);
847 gtk_widget_show(vbox);
849 create_draw_area(user_data, vbox);
851 hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
852 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
853 gtk_widget_show(hbox);
855 bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
856 window_set_cancel_button(user_data->dlg.window, bt_close, window_cancel_button_cb);
858 SIGNAL_CONNECT(user_data->dlg.window, "delete_event", window_delete_event_cb, NULL);
860 gtk_widget_show(user_data->dlg.window);
861 window_present(user_data->dlg.window);
864 /* Return the index array if the node is in the array. Return -1 if there is room in the array
865 * and Return -2 if the array is full
867 /****************************************************************************/
868 gint is_node_array(graph_analysis_data_t* user_data, guint32 node)
871 for (i=0; i<MAX_NUM_NODES; i++){
872 if (user_data->nodes[i] == 0) return -1; /* it is not in the array */
873 if (user_data->nodes[i] == node) return i; /* it is in the array */
875 return -2; /* array full */
879 /* Get the nodes (IPs) from the list */
880 /****************************************************************************/
881 void get_nodes(graph_analysis_data_t* user_data)
884 graph_analysis_item_t *gai;
887 /* fill the node array */
888 list = g_list_first(user_data->graph_info->list);
893 user_data->num_items++;
894 /* check source IP node */
895 index = is_node_array(user_data, gai->ip_src);
897 case -2: /* array full */
898 gai->src_node = NODE_OVERFLOW;
900 case -1: /* not in array */
901 user_data->nodes[user_data->num_nodes] = gai->ip_src;
902 gai->src_node = user_data->num_nodes;
903 user_data->num_nodes++;
905 default: /* it is in the array, just update the src_node */
906 gai->src_node = (guint16)index;
909 /* check destination IP node */
910 index = is_node_array(user_data, gai->ip_dst);
912 case -2: /* array full */
913 gai->dst_node = NODE_OVERFLOW;
915 case -1: /* not in array */
916 user_data->nodes[user_data->num_nodes] = gai->ip_dst;
917 gai->dst_node = user_data->num_nodes;
918 user_data->num_nodes++;
920 default: /* it is in the array, just update the dst_node */
921 gai->dst_node = (guint16)index;
925 list = g_list_next(list);
929 /****************************************************************************/
930 /* XXX only handles IPv4, should add IPv6 support */
931 graph_analysis_data_t* graph_analysis_init(void)
933 graph_analysis_data_t* user_data;
935 user_data = g_malloc(sizeof(graph_analysis_data_t));
938 graph_analysis_init_dlg(user_data);
943 /****************************************************************************/
944 void graph_analysis_create(graph_analysis_data_t* user_data)
947 graph_analysis_reset(user_data);
949 /* get nodes (each node is an IP address) */
950 get_nodes(user_data);
952 /* create the graph windows */
953 dialog_graph_create_window(user_data);
955 /* redraw the graph */
956 dialog_graph_redraw(user_data);
961 /****************************************************************************/
962 void graph_analysis_update(graph_analysis_data_t* user_data)
965 graph_analysis_reset(user_data);
967 /* get nodes (each node is an IP address) */
968 get_nodes(user_data);
970 /* redraw the graph */
971 dialog_graph_redraw(user_data);
973 window_present(user_data->dlg.window);