2 * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
36 #include "epan/filesystem.h"
38 #include "stat_menu.h"
39 #include "dlg_utils.h"
42 #include "compat_macros.h"
43 #include "simple_dialog.h"
44 #include "sctp_stat.h"
46 #define DEFAULT_PIXELS_PER_TICK 2
47 #define MAX_PIXELS_PER_TICK 4
48 #define AUTO_MAX_YSCALE 0
49 #define MAX_TICK_VALUES 5
50 #define DEFAULT_TICK_VALUE 3
52 #define MAX_COUNT_TYPES 3
54 #define COUNT_TYPE_FRAMES 0
55 #define COUNT_TYPE_BYTES 1
56 #define COUNT_TYPE_ADVANCED 2
58 #define LEFT_BORDER 60
59 #define RIGHT_BORDER 10
61 #define BOTTOM_BORDER 50
63 #define SUB_32(a, b) a-b
64 #define MINI(a,b) (a<b)?a:b
65 #define MAXI(a,b) (a>b)?a:b
73 struct data_chunk_header {
83 struct init_chunk_header {
94 struct sack_chunk_header {
112 static void sctp_graph_set_title(struct sctp_udata *u_data);
113 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
116 gint tsn_cmp(gconstpointer aa, gconstpointer bb)
118 const struct tsn_sort* a = aa;
119 const struct tsn_sort* b = bb;
121 if (a->tsnumber < b->tsnumber)
123 if (a->tsnumber == b->tsnumber)
125 if (a->tsnumber > b->tsnumber)
131 static void draw_sack_graph(struct sctp_udata *u_data)
133 GdkColor red_color = {0, 65535, 0, 0};
134 GdkColor green_color = {0, 0, 65535, 0};
135 GdkGC *red_gc, *green_gc;
137 GPtrArray *array = NULL;
138 guint32 min_tsn = 0, max_tsn = 0;
139 guint32 i, size = 0, start, end;
140 gboolean more = FALSE;
142 #if GTK_MAJOR_VERSION < 2
143 GdkColormap *colormap;
146 red_gc = gdk_gc_new(u_data->io->draw_area->window);
147 #if GTK_MAJOR_VERSION < 2
148 colormap = gtk_widget_get_colormap (u_data->io->draw_area);
149 if (!gdk_color_alloc (colormap, &red_color))
151 g_warning ("Couldn't allocate color");
154 gdk_gc_set_foreground(red_gc, &red_color);
156 gdk_gc_set_rgb_fg_color(red_gc, &red_color);
159 green_gc = gdk_gc_new(u_data->io->draw_area->window);
160 #if GTK_MAJOR_VERSION < 2
161 colormap = gtk_widget_get_colormap (u_data->io->draw_area);
162 if (!gdk_color_alloc (colormap, &green_color))
164 g_warning ("Couldn't allocate color");
167 gdk_gc_set_foreground(green_gc, &green_color);
169 gdk_gc_set_rgb_fg_color(green_gc, &green_color);
172 if (u_data->dir == 1)
174 array = u_data->assoc->sort_sack1;
175 size=u_data->assoc->n_sack_chunks_ep1;
176 if (u_data->io->tmp == FALSE)
179 max_tsn = u_data->assoc->max_bytes1;
183 min_tsn = u_data->io->tmp_min_tsn1;
184 max_tsn = u_data->io->tmp_max_tsn1;
187 else if (u_data->dir == 2)
189 array = u_data->assoc->sort_sack2;
190 size = u_data->assoc->n_sack_chunks_ep2;
191 if (u_data->io->tmp == FALSE)
194 max_tsn = u_data->assoc->max_bytes2;
198 min_tsn = u_data->io->tmp_min_tsn2;
199 max_tsn = u_data->io->tmp_max_tsn2;
204 for (i=0; i<size; i++)
206 diff = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs * 1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs - u_data->io->min_x;
207 start = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset;
208 end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
215 if (start >= min_tsn)
217 gdk_draw_line(u_data->io->pixmap,red_gc,
218 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
219 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
220 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
221 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
224 gdk_draw_line(u_data->io->pixmap,green_gc,
225 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
226 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)),
227 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
228 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end+10,min_tsn))*u_data->io->y_interval)));
234 #if GTK_MAJOR_VERSION >= 2
235 g_object_unref(G_OBJECT(red_gc));
236 g_object_unref(G_OBJECT(green_gc));
241 static void draw_tsn_graph(struct sctp_udata *u_data)
243 GPtrArray *array = NULL;
244 guint32 min_tsn = 0, max_tsn = 0;
245 guint32 diff, i, size = 0, start, end;
247 if (u_data->dir == 1)
249 array = u_data->assoc->sort_tsn1;
250 size = u_data->assoc->n_data_chunks_ep1;
251 if (u_data->io->tmp == FALSE)
254 max_tsn = u_data->assoc->max_bytes1;
258 min_tsn = u_data->io->tmp_min_tsn1;
259 max_tsn = u_data->io->tmp_max_tsn1;
262 else if (u_data->dir == 2)
264 array = u_data->assoc->sort_tsn2;
265 size = u_data->assoc->n_data_chunks_ep2;
266 if (u_data->io->tmp == FALSE)
269 max_tsn = u_data->assoc->max_bytes2;
273 min_tsn = u_data->io->tmp_min_tsn2;
274 max_tsn = u_data->io->tmp_max_tsn2;
278 for (i=0; i<size; i++)
280 diff = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs*1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs-u_data->io->min_x;
281 start = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset;
282 end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
283 if (start >= min_tsn)
284 gdk_draw_line(u_data->io->pixmap,
285 u_data->io->draw_area->style->black_gc,
286 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
287 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
288 (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
289 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
295 static void sctp_graph_draw(struct sctp_udata *u_data)
297 int length, lwidth, j, b;
298 guint32 label_width, label_height, distance=5, i, e, sec, w, start, a;
299 char label_string[15];
302 #if GTK_MAJOR_VERSION < 2
308 if (u_data->io->x1_tmp_sec == 0 && u_data->io->x1_tmp_usec == 0)
309 u_data->io->offset = 0;
311 u_data->io->offset = 5;
313 u_data->io->min_x = u_data->io->x1_tmp_sec * 1000000 + u_data->io->x1_tmp_usec;
314 u_data->io->max_x = u_data->io->x2_tmp_sec * 1000000 + u_data->io->x2_tmp_usec;
315 u_data->io->tmp_width = u_data->io->max_x - u_data->io->min_x;
317 if (u_data->dir == 1)
319 if (u_data->io->tmp == FALSE)
321 if (u_data->assoc->sort_tsn1 != NULL)
322 u_data->io->max_y = u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
324 u_data->io->max_y = 0;
325 u_data->io->min_y = 0;
329 u_data->io->max_y = u_data->io->tmp_max_tsn1;
330 u_data->io->min_y = u_data->io->tmp_min_tsn1;
333 else if (u_data->dir == 2)
335 if (u_data->io->tmp == FALSE)
337 if (u_data->assoc->tsn2 != NULL)
338 u_data->io->max_y = u_data->io->tmp_max_tsn2 - u_data->io->tmp_min_tsn2;
340 u_data->io->max_y = 0;
341 u_data->io->min_y = 0;
345 u_data->io->max_y = u_data->io->tmp_max_tsn2;
346 u_data->io->min_y = u_data->io->tmp_min_tsn2;
349 gdk_draw_rectangle(u_data->io->pixmap, u_data->io->draw_area->style->white_gc,
350 TRUE, 0, 0, u_data->io->draw_area->allocation.width,
351 u_data->io->draw_area->allocation.height);
355 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
356 LEFT_BORDER+u_data->io->offset,u_data->io->pixmap_height - BOTTOM_BORDER,
357 u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset, u_data->io->pixmap_height - BOTTOM_BORDER);
358 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
359 u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset, u_data->io->pixmap_height - BOTTOM_BORDER, u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset - 5, u_data->io->pixmap_height - BOTTOM_BORDER - 5);
360 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
361 u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset, u_data->io->pixmap_height - BOTTOM_BORDER, u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset - 5, u_data->io->pixmap_height - BOTTOM_BORDER + 5);
362 u_data->io->axis_width = u_data->io->pixmap_width - LEFT_BORDER - RIGHT_BORDER - u_data->io->offset;
364 u_data->io->x_interval = (float)((u_data->io->axis_width * 1.0) / u_data->io->tmp_width);
367 if (u_data->io->x_interval < 1)
369 dis = 1 / u_data->io->x_interval;
376 for (i=0; i<=e+1; i++)
382 #if GTK_MAJOR_VERSION < 2
383 font = u_data->io->draw_area->style->font;
386 #if GTK_MAJOR_VERSION < 2
387 label_width = gdk_string_width(font, label_string);
388 label_height = gdk_string_height(font, label_string);
390 g_snprintf(label_string, 15, "%d", 0);
391 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
392 layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
393 pango_layout_get_pixel_size(layout, &label_width, &label_height);
397 if (u_data->io->x1_tmp_usec == 0)
398 sec = u_data->io->x1_tmp_sec;
400 sec = u_data->io->x1_tmp_sec+1;
402 if (u_data->io->offset != 0)
404 g_snprintf(label_string, 15, "%u", u_data->io->x1_tmp_sec);
405 #if GTK_MAJOR_VERSION < 2
406 lwidth = gdk_string_width(font, label_string);
407 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
409 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
412 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
413 pango_layout_set_text(layout, label_string, -1);
414 pango_layout_get_pixel_size(layout, &lwidth, NULL);
416 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
418 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
422 w = (guint32)(500 / (guint32)(distance * u_data->io->x_interval));
429 b = 10 + (((u_data->io->min_x / 100000) - 1) % 5);
438 start = u_data->io->min_x / 1000000 * 1000000;
441 start = u_data->io->min_x / 100000;
448 for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
450 if (i >= u_data->io->min_x && i % 1000000 != 0)
453 g_snprintf(label_string, 15, "%d", i%1000000);
459 #if GTK_MAJOR_VERSION < 2
460 lwidth = gdk_string_width(font, label_string);
461 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
462 (guint32)(LEFT_BORDER + u_data->io->offset + (i-u_data->io->min_x) * u_data->io->x_interval - lwidth / 2),
463 u_data->io->pixmap_height - BOTTOM_BORDER + 10,
466 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
467 pango_layout_set_text(layout, label_string, -1);
468 pango_layout_get_pixel_size(layout, &lwidth, NULL);
469 gdk_draw_layout(u_data->io->pixmap,
470 u_data->io->draw_area->style->black_gc,
471 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval - lwidth / 2),
472 u_data->io->pixmap_height - BOTTOM_BORDER + 10,
477 gdk_draw_line(u_data->io->pixmap,
478 u_data->io->draw_area->style->black_gc,
479 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
480 u_data->io->pixmap_height - BOTTOM_BORDER,
481 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
482 u_data->io->pixmap_height - BOTTOM_BORDER + length);
485 if (i % 1000000 == 0)
488 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
489 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
490 u_data->io->pixmap_height - BOTTOM_BORDER,
491 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
492 u_data->io->pixmap_height - BOTTOM_BORDER + 10);
494 g_snprintf(label_string, 15, "%d", sec);
495 #if GTK_MAJOR_VERSION < 2
496 lwidth = gdk_string_width(font, label_string);
497 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
498 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
499 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
502 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
503 pango_layout_set_text(layout, label_string, -1);
504 pango_layout_get_pixel_size(layout, &lwidth, NULL);
506 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
507 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
508 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
514 strcpy(label_string, "sec");
516 #if GTK_MAJOR_VERSION < 2
517 lwidth = gdk_string_width(font, label_string);
518 gdk_draw_string(u_data->io->pixmap,
520 u_data->io->draw_area->style->black_gc,
521 u_data->io->pixmap_width - RIGHT_BORDER - 10,
522 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
525 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
526 pango_layout_set_text(layout, label_string, -1);
527 pango_layout_get_pixel_size(layout, &lwidth, NULL);
528 gdk_draw_layout(u_data->io->pixmap,
529 u_data->io->draw_area->style->black_gc,
530 u_data->io->pixmap_width - RIGHT_BORDER - 10,
531 u_data->io->pixmap_height - BOTTOM_BORDER + 25,
538 gdk_draw_line(u_data->io->pixmap,
539 u_data->io->draw_area->style->black_gc,
540 LEFT_BORDER,TOP_BORDER - u_data->io->offset,
542 u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset);
543 gdk_draw_line(u_data->io->pixmap,
544 u_data->io->draw_area->style->black_gc,
546 TOP_BORDER - u_data->io->offset,
548 TOP_BORDER - u_data->io->offset + 5);
549 gdk_draw_line(u_data->io->pixmap,
550 u_data->io->draw_area->style->black_gc,
552 TOP_BORDER - u_data->io->offset,
554 TOP_BORDER - u_data->io->offset + 5);
556 u_data->io->y_interval = (float)(((u_data->io->pixmap_height - TOP_BORDER - BOTTOM_BORDER) * 1.0)/(u_data->io->max_y - u_data->io->min_y));
559 if (u_data->io->y_interval < 1)
561 dis = 1 / u_data->io->y_interval;
569 distance = distance * 10;
572 if (u_data->io->max_y > 0)
574 for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
576 if (i >= u_data->io->min_y)
579 g_snprintf(label_string, 15, "%d", i);
581 if (i%distance == 0 || (distance <= 5 && u_data->io->y_interval > 10))
585 #if GTK_MAJOR_VERSION < 2
586 lwidth = gdk_string_width(font, label_string);
587 gdk_draw_string(u_data->io->pixmap,font,
588 u_data->io->draw_area->style->black_gc,
589 LEFT_BORDER - length - lwidth - 5,
590 (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval - 3),
593 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
594 pango_layout_set_text(layout, label_string, -1);
595 pango_layout_get_pixel_size(layout, &lwidth, NULL);
596 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
597 LEFT_BORDER - length - lwidth - 5,
598 (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval - 3),
602 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
603 LEFT_BORDER - length,
604 (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval),
606 (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval));
611 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
615 static void sctp_graph_redraw(struct sctp_udata *u_data)
619 u_data->io->needs_redraw = TRUE;
621 sctp_graph_draw(u_data);
622 switch (u_data->io->graph_type)
625 draw_sack_graph(u_data);
626 draw_tsn_graph(u_data);
629 draw_tsn_graph(u_data);
632 draw_sack_graph(u_data);
635 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
642 gdk_draw_pixmap(u_data->io->draw_area->window,
643 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
647 u_data->io->draw_area->allocation.width,
648 u_data->io->draw_area->allocation.height);
652 static void on_sack_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
654 u_data = (struct sctp_udata *) u_data;
655 u_data->io->graph_type = 2;
656 sctp_graph_redraw(u_data);
659 static void on_tsn_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
661 u_data->io->graph_type = 1;
662 sctp_graph_redraw(u_data);
665 static void on_both_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
667 u_data->io->graph_type = 0;
668 sctp_graph_redraw(u_data);
672 sctp_graph_close_cb(GtkWidget* widget _U_, gpointer u_data)
674 struct sctp_udata *udata;
677 udata = (struct sctp_udata *)u_data;
678 dir = udata->dir - 1;
679 gtk_grab_remove(GTK_WIDGET(udata->io->window));
680 gtk_widget_destroy(GTK_WIDGET(udata->io->window));
686 configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, struct sctp_udata *u_data)
692 if(u_data->io->pixmap){
693 gdk_pixmap_unref(u_data->io->pixmap);
694 u_data->io->pixmap = NULL;
697 u_data->io->pixmap = gdk_pixmap_new(widget->window,
698 widget->allocation.width,
699 widget->allocation.height,
701 u_data->io->pixmap_width = widget->allocation.width;
702 u_data->io->pixmap_height = widget->allocation.height;
704 gdk_draw_rectangle(u_data->io->pixmap,
705 widget->style->white_gc,
708 widget->allocation.width,
709 widget->allocation.height);
710 sctp_graph_redraw(u_data);
715 expose_event(GtkWidget *widget, GdkEventExpose *event)
719 ios=(sctp_graph_t *)OBJECT_GET_DATA(widget, "sctp_graph_t");
724 gdk_draw_pixmap(widget->window,
725 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
727 event->area.x, event->area.y,
728 event->area.x, event->area.y,
729 event->area.width, event->area.height);
736 on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
738 sctp_min_max_t *tmp_minmax;
740 if (u_data->io->rectangle==TRUE)
742 tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
744 u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
745 u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
746 u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
747 u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
748 tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
749 tmp_minmax->tmp_min_usecs= u_data->io->x1_tmp_usec;
750 tmp_minmax->tmp_max_secs= u_data->io->x2_tmp_sec;
751 tmp_minmax->tmp_max_usecs= u_data->io->x2_tmp_usec;
752 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
753 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
754 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
755 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
756 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
757 u_data->io->length = g_slist_length(u_data->assoc->min_max);
758 u_data->io->tmp=TRUE;
759 u_data->io->rectangle=FALSE;
760 sctp_graph_redraw(u_data);
765 on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
767 sctp_min_max_t *tmp_minmax, *mm;
770 l = g_slist_length(u_data->assoc->min_max);
772 if (u_data->assoc->min_max!=NULL)
774 mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
775 u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
780 tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
781 u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
782 u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
783 u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
784 u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
785 u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
786 u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
787 u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
788 u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
789 u_data->io->tmp=TRUE;
793 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
794 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
795 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
796 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
797 u_data->io->tmp_min_tsn1=0;
798 u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
799 u_data->io->tmp_min_tsn2=0;
800 u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
801 u_data->io->tmp=FALSE;
806 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
807 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
808 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
809 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
810 u_data->io->tmp_min_tsn1=0;
811 u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
812 u_data->io->tmp_min_tsn2=0;
813 u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
814 u_data->io->tmp=FALSE;
816 sctp_graph_redraw(u_data);
821 on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
825 if (u_data->io->rectangle==TRUE)
827 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
829 (gint)floor(MINI(u_data->io->x_old,u_data->io->x_new)),
830 (gint)floor(MINI(u_data->io->y_old,u_data->io->y_new)),
831 (gint)abs((long)(u_data->io->x_new-u_data->io->x_old)),
832 (gint)abs((long)(u_data->io->y_new-u_data->io->y_old)));
833 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
839 gdk_draw_pixmap(u_data->io->draw_area->window,
840 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
844 (gint)abs((long)(u_data->io->x_new-u_data->io->x_old)),
845 (gint)abs((long)(u_data->io->y_new-u_data->io->y_old)));
846 sctp_graph_redraw(u_data);
849 u_data->io->x_old=event->x;
850 u_data->io->y_old=event->y;
851 if (u_data->io->y_old>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
852 u_data->io->y_old=u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
853 if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
854 u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
855 u_data->io->rectangle=FALSE;
862 on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
866 guint32 helpy, x1_tmp, x2_tmp;
868 if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
869 event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
870 if (event->x < LEFT_BORDER+u_data->io->offset)
871 event->x = LEFT_BORDER+u_data->io->offset;
873 if (abs((long)(event->x-u_data->io->x_old))>10 || abs((long)(event->y-u_data->io->y_old))>10)
875 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
877 (gint)floor(MINI(u_data->io->x_old,event->x)), (gint)floor(MINI(u_data->io->y_old,event->y)),
878 (gint)abs((long)(event->x-u_data->io->x_old)),
879 (gint)abs((long)(event->y-u_data->io->y_old)));
880 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
886 gdk_draw_pixmap(u_data->io->draw_area->window,
887 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
891 u_data->io->draw_area->allocation.width,
892 u_data->io->draw_area->allocation.height);
894 x1_tmp=(unsigned int)floor(u_data->io->min_x+((u_data->io->x_old-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
895 x2_tmp=(unsigned int)floor(u_data->io->min_x+((event->x-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
896 helpx=MINI(x1_tmp, x2_tmp);
902 u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
903 u_data->io->x1_tmp_usec=x1_tmp%1000000;
904 u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
905 u_data->io->x2_tmp_usec=x2_tmp%1000000;
907 u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->y_old)/u_data->io->y_interval);
908 u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-event->y)/u_data->io->y_interval);
909 helpy = MINI(u_data->io->y1_tmp, u_data->io->y2_tmp);
910 u_data->io->y2_tmp = MAXI(u_data->io->y1_tmp, u_data->io->y2_tmp);
911 u_data->io->y1_tmp = helpy;
912 u_data->io->x_new=event->x;
913 u_data->io->y_new=event->y;
914 u_data->io->rectangle=TRUE;
920 static void init_sctp_graph_window(struct sctp_udata *u_data)
924 GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt, *zoomout_bt;
925 GtkTooltips *tooltip_in, *tooltip_out;
927 /* create the main window */
929 u_data->io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
931 gtk_widget_set_name(u_data->io->window, "SCTP Graphics");
933 vbox=gtk_vbox_new(FALSE, 0);
934 gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
935 gtk_widget_show(vbox);
937 create_draw_area(vbox, u_data);
939 sctp_graph_set_title(u_data);
941 hbox = gtk_hbutton_box_new();
942 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
943 gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
944 gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
945 gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
946 gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
947 gtk_widget_show(hbox);
949 sack_bt = gtk_button_new_with_label ("Adv. Rec. Window");
950 gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
951 gtk_widget_show(sack_bt);
953 gtk_signal_connect(GTK_OBJECT(sack_bt), "clicked", (GtkSignalFunc)on_sack_bt, u_data);
955 tsn_bt = gtk_button_new_with_label ("Data bytes sent");
956 gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
957 gtk_widget_show(tsn_bt);
958 SIGNAL_CONNECT(tsn_bt, "clicked", on_tsn_bt, u_data);
960 both_bt = gtk_button_new_with_label ("Show both");
961 gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
962 gtk_widget_show(both_bt);
963 SIGNAL_CONNECT(both_bt, "clicked", on_both_bt, u_data);
965 zoomin_bt = gtk_button_new_with_label ("Zoom in");
966 gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
967 gtk_widget_show(zoomin_bt);
968 SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
969 tooltip_in = gtk_tooltips_new();
970 gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Draw a rectangle around the area you want to zoom in", NULL);
972 zoomout_bt = gtk_button_new_with_label ("Zoom out");
973 gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
974 gtk_widget_show(zoomout_bt);
975 SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
976 tooltip_out = gtk_tooltips_new();
977 gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
980 bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
981 gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
982 gtk_widget_show(bt_close);
983 SIGNAL_CONNECT(bt_close, "clicked", sctp_graph_close_cb, u_data);
985 gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_press_event",(GtkSignalFunc)on_button_press, u_data);
986 gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
987 gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
988 /* dlg_set_cancel(u_data->io->window, bt_close); */
991 gtk_widget_show(u_data->io->window);
994 static void sctp_graph_set_title(struct sctp_udata *u_data)
998 if(!u_data->io->window)
1002 title = g_strdup_printf("SCTP Data and Adv.Rcv.Window over Time: %s Port1 %u Port2 %u Endpoint %u",
1003 cf_get_display_name(&cfile), u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
1004 gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
1010 gtk_sctpgraph_init(struct sctp_udata *u_data)
1014 sctp_min_max_t* tmp_minmax;
1016 io=g_malloc(sizeof(sctp_graph_t));
1017 io->needs_redraw=TRUE;
1018 io->x_interval=1000;
1022 io->pixmap_width=800;
1023 io->pixmap_height=600;
1029 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1030 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1031 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1032 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1033 u_data->io->tmp_min_tsn1=0;
1034 u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
1035 u_data->io->tmp_min_tsn2=0;
1036 u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
1037 u_data->io->tmp=FALSE;
1038 tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
1039 tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
1040 tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
1041 tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
1042 tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
1043 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
1044 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
1045 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
1046 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
1047 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1050 init_sctp_graph_window(u_data);
1051 sctp_graph_redraw(u_data);
1056 quit(GtkObject *object _U_, gpointer user_data)
1058 struct sctp_udata *u_data=(struct sctp_udata*)user_data;
1060 decrease_childcount(u_data->parent);
1061 remove_child(u_data, u_data->parent);
1063 u_data->assoc->min_max = NULL;
1069 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
1071 u_data->io->draw_area=gtk_drawing_area_new();
1072 SIGNAL_CONNECT(u_data->io->draw_area, "destroy", quit, u_data);
1073 OBJECT_SET_DATA(u_data->io->draw_area, "sctp_graph_t", u_data->io);
1075 WIDGET_SET_SIZE(u_data->io->draw_area, u_data->io->pixmap_width, u_data->io->pixmap_height);
1077 /* signals needed to handle backing pixmap */
1078 SIGNAL_CONNECT(u_data->io->draw_area, "expose_event", expose_event, NULL);
1079 SIGNAL_CONNECT(u_data->io->draw_area, "configure_event", configure_event, u_data);
1081 gtk_widget_show(u_data->io->draw_area);
1082 gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
1085 void insertion(GPtrArray *array, guint32 N)
1089 struct tsn_sort *help=NULL;
1093 v = ((struct tsn_sort*)(g_ptr_array_index(array,i)))->tsnumber;
1095 while (j>=1 && ((struct tsn_sort*)(g_ptr_array_index(array, j-1)))->tsnumber > v)
1097 help=g_ptr_array_index(array, j);
1098 g_ptr_array_index(array, j)=g_ptr_array_index(array, j-1);
1099 g_ptr_array_index(array, j-1)=help;
1102 ((struct tsn_sort*)(g_ptr_array_index(array, j)))->tsnumber=v;
1106 void set_arw_offsets(struct sctp_udata *u_data)
1108 GPtrArray *s_array=NULL, *t_array=NULL;
1111 if (u_data->dir==1 && u_data->assoc->n_sack_chunks_ep1>0)
1113 s_array=u_data->assoc->sort_sack1;
1114 t_array=u_data->assoc->sort_tsn1;
1115 insertion(s_array,u_data->assoc->n_sack_chunks_ep1);
1117 for (i=0; i<u_data->assoc->n_sack_chunks_ep1; i++)
1119 while (((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->tsnumber > ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->tsnumber)
1123 ((struct tsn_sort*)(g_ptr_array_index(s_array,i)))->offset = ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->offset
1124 + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;
1127 u_data->assoc->sort_sack1=s_array;
1130 if (u_data->dir==2 && u_data->assoc->n_sack_chunks_ep2>0)
1132 s_array=u_data->assoc->sort_sack2;
1133 t_array=u_data->assoc->sort_tsn2;
1134 insertion(s_array,u_data->assoc->n_sack_chunks_ep2);
1136 for (i=0; i<u_data->assoc->n_sack_chunks_ep2; i++)
1138 while (((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->tsnumber > ((struct tsn_sort*)(g_ptr_array_index(t_array,j)))->tsnumber)
1142 ((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->offset = ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->offset
1143 + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;
1145 u_data->assoc->sort_sack2=s_array;
1149 void compute_offsets(struct sctp_udata *u_data)
1151 struct tsn_sort t_sort;
1152 GPtrArray *array=NULL;
1157 if (u_data->dir==1 && u_data->assoc->n_array_tsn1>0)
1159 array=u_data->assoc->sort_tsn1;
1160 insertion(array,u_data->assoc->n_array_tsn1);
1162 for (i=0; i<u_data->assoc->n_array_tsn1; i++)
1164 ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset=sum;
1165 t_sort.tsnumber=((struct tsn_sort*)(g_ptr_array_index(array, i)))->tsnumber;
1166 if (t_sort.tsnumber>tsntmp)
1167 sum+=((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
1168 tsntmp=t_sort.tsnumber;
1170 u_data->assoc->max_bytes1= ((struct tsn_sort*)(g_ptr_array_index(array, i-1)))->offset + ((struct tsn_sort*)(g_ptr_array_index(array, i-1)))->length;
1171 u_data->assoc->sort_tsn1=array;
1173 if (u_data->dir==2 && u_data->assoc->n_array_tsn2>0)
1176 array=u_data->assoc->sort_tsn2;
1177 insertion(array,u_data->assoc->n_array_tsn2);
1179 for (i=0; i<u_data->assoc->n_array_tsn2; i++)
1181 ((struct tsn_sort*)(g_ptr_array_index(array,i)))->offset=sum;
1182 t_sort.tsnumber=((struct tsn_sort*)(g_ptr_array_index(array, i)))->tsnumber;
1183 if (t_sort.tsnumber>tsntmp)
1184 sum+=((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
1185 tsntmp=t_sort.tsnumber;
1188 u_data->assoc->max_bytes2= ((struct tsn_sort*)(g_ptr_array_index(array, u_data->assoc->n_data_chunks_ep2-1)))->offset + ((struct tsn_sort*)(g_ptr_array_index(array, u_data->assoc->n_data_chunks_ep2-1)))->length;
1189 u_data->assoc->sort_tsn2=array;
1193 void create_byte_graph(guint16 dir, struct sctp_analyse* userdata)
1195 struct sctp_udata *u_data;
1197 u_data=g_malloc(sizeof(struct sctp_udata));
1198 u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
1199 u_data->assoc=userdata->assoc;
1202 u_data->parent = userdata;
1203 if ((u_data->dir==1 && (u_data->assoc->n_array_tsn1==0))|| (u_data->dir==2 && (u_data->assoc->n_array_tsn2==0)))
1204 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
1207 set_child(u_data, u_data->parent);
1208 increase_childcount(u_data->parent);
1209 compute_offsets(u_data);
1210 set_arw_offsets(u_data);
1211 gtk_sctpgraph_init(u_data);