Witness: enum witness_notifyResponse_type
[wireshark-wip.git] / ui / gtk / sctp_graph_dlg.c
blobd09175e7a446e724845d6c09726193a219feff69
1 /*
2 * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
3 * Copyright 2009, Varun Notibala <nbvarun [AT] gmail.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <math.h>
31 #include <string.h>
33 #include <gtk/gtk.h>
35 #include "epan/filesystem.h"
36 #include <epan/strutil.h>
38 #include "../globals.h"
39 #include "ui/ui_util.h"
40 #include "ui/simple_dialog.h"
42 #include "ui/gtk/dlg_utils.h"
43 #include "ui/gtk/main.h"
44 #include "ui/tap-sctp-analysis.h"
45 #include "ui/gtk/sctp_stat_gtk.h"
46 #include "ui/gtk/gui_utils.h"
47 #include "ui/gtk/old-gtk-compat.h"
49 #define DEFAULT_PIXELS_PER_TICK 2
50 #define MAX_PIXELS_PER_TICK 4
51 #define AUTO_MAX_YSCALE 0
52 #define MAX_TICK_VALUES 5
53 #define DEFAULT_TICK_VALUE 3
54 #define MAX_YSCALE 22
55 #define MAX_COUNT_TYPES 3
57 #define COUNT_TYPE_FRAMES 0
58 #define COUNT_TYPE_BYTES 1
59 #define COUNT_TYPE_ADVANCED 2
61 #define LEFT_BORDER 60
62 #define RIGHT_BORDER 10
63 #define TOP_BORDER 10
64 #define BOTTOM_BORDER 50
66 #define SUB_32(a, b) ((a)-(b))
67 #define POINT_SIZE 1
69 static GtkWidget * sack_bt;
72 * Global variables that help in redrawing graph
73 * for SACK and NRSACK
75 static guint8 gIsSackChunkPresent = 0;
76 static guint8 gIsNRSackChunkPresent = 0;
78 struct chunk_header {
79 guint8 type;
80 guint8 flags;
81 guint16 length;
84 struct data_chunk_header {
85 guint8 type;
86 guint8 flags;
87 guint16 length;
88 guint32 tsn;
89 guint16 sid;
90 guint16 ssn;
91 guint32 ppi;
94 struct init_chunk_header {
95 guint8 type;
96 guint8 flags;
97 guint16 length;
98 guint32 initiate_tag;
99 guint32 a_rwnd;
100 guint16 mos;
101 guint16 mis;
102 guint32 initial_tsn;
105 struct gaps {
106 guint16 start;
107 guint16 end;
110 struct sack_chunk_header {
111 guint8 type;
112 guint8 flags;
113 guint16 length;
114 guint32 cum_tsn_ack;
115 guint32 a_rwnd;
116 guint16 nr_of_gaps;
117 guint16 nr_of_dups;
118 struct gaps gaps[1];
121 struct nr_sack_chunk_header {
122 guint8 type;
123 guint8 flags;
124 guint16 length;
125 guint32 cum_tsn_ack;
126 guint32 a_rwnd;
127 guint16 nr_of_gaps;
128 guint16 nr_of_nr_gaps;
129 guint16 nr_of_dups;
130 guint16 reserved;
131 struct gaps gaps[1];
134 static gboolean label_set = FALSE;
135 static guint32 max_tsn=0, min_tsn=0;
136 static void sctp_graph_set_title(struct sctp_udata *u_data);
137 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
138 static GtkWidget *zoomout_bt;
139 #if defined(_WIN32) && !defined(__MINGW32__) && (_MSC_VER < 1800)
140 /* Starting VS2013, rint already defined in math.h. No need to redefine */
141 static int rint (double ); /* compiler template for Windows */
142 #endif
144 static void
145 draw_sack_graph(struct sctp_udata *u_data)
147 tsn_t *sack;
148 GList *list=NULL, *tlist;
149 guint16 gap_start=0, gap_end=0, i, j, nr, dup_nr;
150 guint8 type;
151 guint32 tsnumber, dupx;
152 gint xvalue, yvalue;
153 GdkRGBA red_color = {1.0, 0.0, 0.0, 1.0};
154 GdkRGBA green_color = {0.0, 1.0, 0.0, 1.0};
155 GdkRGBA cyan_color = {0.0, 1.0, 1.0, 1.0};
157 struct sack_chunk_header *sack_header;
158 struct gaps *gap;
159 guint32 /*max_num,*/ diff;
160 guint32 *dup_list;
161 cairo_t * cr = NULL;
163 if (u_data->dir==2)
166 list = g_list_last(u_data->assoc->sack2);
167 if (u_data->io->tmp==FALSE)
169 min_tsn=u_data->assoc->min_tsn2;
170 max_tsn=u_data->assoc->max_tsn2;
172 else
174 min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
175 max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
178 else if (u_data->dir==1)
180 list = g_list_last(u_data->assoc->sack1);
181 if (u_data->io->tmp==FALSE)
183 min_tsn=u_data->assoc->min_tsn1;
184 max_tsn=u_data->assoc->max_tsn1;
186 else
188 min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
189 max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
193 while (list)
195 sack = (tsn_t*) (list->data);
196 tlist = g_list_first(sack->tsns);
197 while (tlist)
199 type = ((struct chunk_header *)tlist->data)->type;
201 if (type == SCTP_SACK_CHUNK_ID)
203 gIsSackChunkPresent = 1;
204 sack_header =(struct sack_chunk_header *)tlist->data;
205 nr=g_ntohs(sack_header->nr_of_gaps);
206 tsnumber = g_ntohl(sack_header->cum_tsn_ack);
207 dup_nr=g_ntohs(sack_header->nr_of_dups);
209 if (sack->secs>=u_data->io->x1_tmp_sec)
211 if (nr>0)
213 gap = &sack_header->gaps[0];
214 for(i=0;i<nr; i++)
216 gap_start=g_ntohs(gap->start);
217 gap_end = g_ntohs(gap->end);
218 /* max_num=gap_end+tsnumber; */
219 for (j=gap_start; j<=gap_end; j++)
221 if (u_data->io->uoff)
222 diff = sack->secs - u_data->io->min_x;
223 else
224 diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
225 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
226 yvalue = (guint32)(u_data->io->surface_height-BOTTOM_BORDER-POINT_SIZE-u_data->io->offset-((SUB_32(j+tsnumber,min_tsn))*u_data->io->y_interval));
227 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
228 xvalue <= u_data->io->surface_width-RIGHT_BORDER+u_data->io->offset &&
229 yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
230 yvalue <= u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset) {
231 #if GTK_CHECK_VERSION(2,22,0)
232 cr = cairo_create (u_data->io->surface);
233 #else
234 cr = gdk_cairo_create (u_data->io->pixmap);
235 #endif
236 gdk_cairo_set_source_rgba (cr, &green_color);
237 cairo_arc(cr,
238 xvalue,
239 yvalue,
240 POINT_SIZE,
242 2 * G_PI);
243 cairo_fill(cr);
244 cairo_destroy(cr);
247 if (i < nr-1)
248 gap++;
252 else
253 max_num=tsnumber;
255 if (tsnumber>=min_tsn)
257 if (u_data->io->uoff)
258 diff = sack->secs - u_data->io->min_x;
259 else
260 diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
261 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
262 yvalue = (guint32)(u_data->io->surface_height-BOTTOM_BORDER-POINT_SIZE -u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
263 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
264 xvalue <= u_data->io->surface_width-RIGHT_BORDER+u_data->io->offset &&
265 yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
266 yvalue <= u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset)
268 #if GTK_CHECK_VERSION(2,22,0)
269 cr = cairo_create (u_data->io->surface);
270 #else
271 cr = gdk_cairo_create (u_data->io->pixmap);
272 #endif
273 gdk_cairo_set_source_rgba (cr, &red_color);
274 cairo_arc(cr,
275 xvalue,
276 yvalue,
277 POINT_SIZE,
279 2 * G_PI);
280 cairo_fill(cr);
281 cairo_destroy(cr);
285 if (dup_nr > 0)
287 dup_list = &sack_header->a_rwnd + 2 + nr;
288 for (i = 0; i < dup_nr; i++)
290 dupx = g_ntohl(dup_list[i]);
291 if (dupx >= min_tsn)
293 if (u_data->io->uoff)
294 diff = sack->secs - u_data->io->min_x;
295 else
296 diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
297 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
298 yvalue = (guint32)(u_data->io->surface_height-BOTTOM_BORDER-POINT_SIZE -u_data->io->offset-((SUB_32(dupx,min_tsn))*u_data->io->y_interval));
299 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
300 xvalue <= u_data->io->surface_width-RIGHT_BORDER+u_data->io->offset &&
301 yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
302 yvalue <= u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset) {
303 #if GTK_CHECK_VERSION(2,22,0)
304 cr = cairo_create (u_data->io->surface);
305 #else
306 cr = gdk_cairo_create (u_data->io->pixmap);
307 #endif
308 gdk_cairo_set_source_rgba (cr, &cyan_color);
309 cairo_arc(cr,
310 xvalue,
311 yvalue,
312 POINT_SIZE,
314 2 * G_PI);
315 cairo_fill(cr);
316 cairo_destroy(cr);
323 tlist = g_list_next(tlist);
325 list = g_list_previous(list);
330 * This function plots the NR_SACK gap ack and
331 * nr gap acks.
332 * Red dot - Cumulative TSN ack
333 * Green dot - Gap ack
334 * Blue circle - NR Gap ack
336 static void
337 draw_nr_sack_graph(struct sctp_udata *u_data)
339 tsn_t *sack;
340 GList *list=NULL, *tlist;
341 guint16 gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps;
342 guint8 type;
343 guint32 tsnumber, j;
344 gint xvalue, yvalue;
345 GdkRGBA red_color = {1.0, 0.0, 0.0, 1.0};
346 GdkRGBA green_color = {0.0, 1.0, 0.0, 1.0};
347 GdkRGBA blue_color = {0.0, 0.0, 1.0, 1.0};
348 struct nr_sack_chunk_header *nr_sack_header;
349 struct gaps *nr_gap;
350 guint32 /*max_num,*/ diff;
351 /* This holds the sum of gap acks and nr gap acks */
352 guint16 total_gaps = 0;
353 cairo_t *cr = NULL;
355 if (u_data->dir==2)
357 list = g_list_last(u_data->assoc->sack2);
358 if (u_data->io->tmp==FALSE)
360 min_tsn=u_data->assoc->min_tsn2;
361 max_tsn=u_data->assoc->max_tsn2;
363 else
365 min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
366 max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
369 else if (u_data->dir==1)
371 list = g_list_last(u_data->assoc->sack1);
372 if (u_data->io->tmp==FALSE)
374 min_tsn=u_data->assoc->min_tsn1;
375 max_tsn=u_data->assoc->max_tsn1;
377 else
379 min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
380 max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
383 while (list)
385 sack = (tsn_t*) (list->data);
386 tlist = g_list_first(sack->tsns);
387 while (tlist)
389 type = ((struct chunk_header *)tlist->data)->type;
391 * The tlist->data is memcpy ied to the appropriate structure
392 * They entire raw tvb bytes are copied on to one of the *_chunk_header
393 * structures in sctp_stat.c
395 if (type == SCTP_NR_SACK_CHUNK_ID)
397 gIsNRSackChunkPresent = 1;
398 nr_sack_header =(struct nr_sack_chunk_header *)tlist->data;
399 numberOf_nr_gaps=g_ntohs(nr_sack_header->nr_of_nr_gaps);
400 numberOf_gaps=g_ntohs(nr_sack_header->nr_of_gaps);
401 tsnumber = g_ntohl(nr_sack_header->cum_tsn_ack);
402 total_gaps = numberOf_gaps + numberOf_nr_gaps;
403 if (sack->secs>=u_data->io->x1_tmp_sec)
405 /* If the number of nr_gaps is greater than 0 */
406 if ( total_gaps > 0 )
408 nr_gap = &nr_sack_header->gaps[0];
409 for ( i=0; i < total_gaps; i++ )
411 gap_start=g_ntohs(nr_gap->start);
412 gap_end = g_ntohs(nr_gap->end);
413 /* max_num= gap_end + tsnumber; */
414 for ( j = gap_start; j <= gap_end; j++)
416 if (u_data->io->uoff)
417 diff = sack->secs - u_data->io->min_x;
418 else
419 diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
420 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
421 yvalue = (guint32)(u_data->io->surface_height-BOTTOM_BORDER-POINT_SIZE-u_data->io->offset-((SUB_32(j+tsnumber,min_tsn))*u_data->io->y_interval));
422 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
423 xvalue <= u_data->io->surface_width-RIGHT_BORDER+u_data->io->offset &&
424 yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
425 yvalue <= u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset)
427 /* Check if this is an GAP ACK or NR GAP ACK */
428 if ( i >= numberOf_gaps)
430 /* This is a nr gap ack */
431 #if GTK_CHECK_VERSION(2,22,0)
432 cr = cairo_create (u_data->io->surface);
433 #else
434 cr = gdk_cairo_create (u_data->io->pixmap);
435 #endif
436 gdk_cairo_set_source_rgba (cr, &blue_color);
437 cairo_arc(cr,
438 xvalue,
439 yvalue,
440 POINT_SIZE,
442 2 * G_PI);
443 cairo_stroke(cr);
444 cairo_destroy(cr);
447 /* All NR GAP Acks are also gap acks, so plot these as
448 * gap acks - green dot.
449 * These will be shown as points with a green dot - GAP ACK
450 * surrounded by a blue circle - NR GAP ack
452 #if GTK_CHECK_VERSION(2,22,0)
453 cr = cairo_create (u_data->io->surface);
454 #else
455 cr = gdk_cairo_create (u_data->io->pixmap);
456 #endif
457 gdk_cairo_set_source_rgba (cr, &green_color);
458 cairo_arc(cr,
459 xvalue,
460 yvalue,
461 POINT_SIZE,
463 2 * G_PI);
464 cairo_fill(cr);
465 cairo_destroy(cr);
467 else
469 /* This is just a gap ack */
470 #if GTK_CHECK_VERSION(2,22,0)
471 cr = cairo_create (u_data->io->surface);
472 #else
473 cr = gdk_cairo_create (u_data->io->pixmap);
474 #endif
475 gdk_cairo_set_source_rgba (cr, &green_color);
476 cairo_arc(cr,
477 xvalue,
478 yvalue,
479 POINT_SIZE,
481 2 * G_PI);
482 cairo_fill(cr);
483 cairo_destroy(cr);
487 if (i < total_gaps-1)
488 nr_gap++;
492 else
493 max_num=tsnumber;
495 if (tsnumber>=min_tsn)
497 if (u_data->io->uoff)
498 diff = sack->secs - u_data->io->min_x;
499 else
500 diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
501 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
502 yvalue = (guint32)(u_data->io->surface_height-BOTTOM_BORDER-POINT_SIZE -u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
503 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
504 xvalue <= u_data->io->surface_width-RIGHT_BORDER+u_data->io->offset &&
505 yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
506 yvalue <= u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset) {
507 #if GTK_CHECK_VERSION(2,22,0)
508 cr = cairo_create (u_data->io->surface);
509 #else
510 cr = gdk_cairo_create (u_data->io->pixmap);
511 #endif
512 gdk_cairo_set_source_rgba (cr, &red_color);
513 cairo_arc(cr,
514 xvalue,
515 yvalue,
516 POINT_SIZE,
518 2 * G_PI);
519 cairo_fill(cr);
520 cairo_destroy(cr);
525 tlist = g_list_next(tlist);
527 list = g_list_previous(list);
531 static void
532 draw_tsn_graph(struct sctp_udata *u_data)
534 tsn_t *tsn;
535 GList *list=NULL, *tlist;
536 guint8 type;
537 guint32 tsnumber=0;
538 guint32 min_secs=0, diff;
539 gint xvalue, yvalue;
540 cairo_t *cr = NULL;
541 GdkRGBA black_color = {0.0, 0.0, 0.0, 1.0};
542 GdkRGBA pink_color = {1.0, 0.6, 0.8, 1.0};
544 if (u_data->dir == 1)
546 list = g_list_last(u_data->assoc->tsn1);
547 if (u_data->io->tmp == FALSE)
549 min_tsn = u_data->assoc->min_tsn1;
550 max_tsn = u_data->assoc->max_tsn1;
552 else
554 min_tsn = u_data->assoc->min_tsn1 + u_data->io->tmp_min_tsn1;
555 max_tsn = u_data->assoc->min_tsn1 + u_data->io->tmp_max_tsn1;
558 else if (u_data->dir == 2)
560 list = g_list_last(u_data->assoc->tsn2);
561 if (u_data->io->tmp == FALSE)
563 min_tsn = u_data->assoc->min_tsn2;
564 max_tsn = u_data->assoc->max_tsn2;
566 else
568 min_tsn = u_data->assoc->min_tsn2 + u_data->io->tmp_min_tsn2;
569 max_tsn = u_data->assoc->min_tsn2 + u_data->io->tmp_max_tsn2;
573 while (list)
575 tsn = (tsn_t*) (list->data);
576 tlist = g_list_first(tsn->tsns);
577 while (tlist)
579 type = ((struct chunk_header *)tlist->data)->type;
580 if (type == SCTP_DATA_CHUNK_ID || type == SCTP_FORWARD_TSN_CHUNK_ID)
581 tsnumber = g_ntohl(((struct data_chunk_header *)tlist->data)->tsn);
582 if (tsnumber >= min_tsn && tsnumber <= max_tsn && tsn->secs >= min_secs)
584 if (u_data->io->uoff) {
585 diff = tsn->secs - u_data->io->min_x;
586 } else {
587 diff = tsn->secs * 1000000 + tsn->usecs - u_data->io->min_x;
589 xvalue = (guint32)(LEFT_BORDER + u_data->io->offset + u_data->io->x_interval * diff);
590 yvalue = (guint32)(u_data->io->surface_height - BOTTOM_BORDER - POINT_SIZE - u_data->io->offset - ((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
591 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
592 xvalue <= u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset &&
593 yvalue >= TOP_BORDER - u_data->io->offset - POINT_SIZE &&
594 yvalue <= u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset) {
595 #if GTK_CHECK_VERSION(2,22,0)
596 cr = cairo_create (u_data->io->surface);
597 #else
598 cr = gdk_cairo_create (u_data->io->pixmap);
599 #endif
600 if (type == SCTP_DATA_CHUNK_ID)
601 gdk_cairo_set_source_rgba (cr, &black_color);
602 else
603 gdk_cairo_set_source_rgba (cr, &pink_color);
604 cairo_arc(cr,
605 xvalue,
606 yvalue,
607 POINT_SIZE,
609 2 * G_PI);
610 cairo_fill(cr);
611 cairo_destroy(cr);
615 tlist = g_list_next(tlist);
617 list = g_list_previous(list);
622 static void
623 sctp_graph_draw(struct sctp_udata *u_data)
625 int length, lwidth;
626 guint32 distance=5, i, e, sec, w, start, a, b, j;
627 gint label_width, label_height;
628 char label_string[15];
629 gfloat dis;
630 gboolean write_label = FALSE;
631 PangoLayout *layout;
632 GtkAllocation widget_alloc;
633 cairo_t *cr;
635 if (u_data->io->x1_tmp_sec==0 && u_data->io->x1_tmp_usec==0)
636 u_data->io->offset=0;
637 else
638 u_data->io->offset=5;
640 if (u_data->io->x2_tmp_sec - u_data->io->x1_tmp_sec > 1500)
642 u_data->io->min_x=u_data->io->x1_tmp_sec;
643 u_data->io->max_x=u_data->io->x2_tmp_sec;
644 u_data->io->uoff = TRUE;
646 else
648 u_data->io->min_x=(guint32)(u_data->io->x1_tmp_sec*1000000.0+u_data->io->x1_tmp_usec);
649 u_data->io->max_x=(guint32)(u_data->io->x2_tmp_sec*1000000.0+u_data->io->x2_tmp_usec);
650 u_data->io->uoff = FALSE;
653 u_data->io->tmp_width=u_data->io->max_x-u_data->io->min_x;
655 if (u_data->dir==1)
657 if (u_data->io->tmp==FALSE)
659 if (u_data->assoc->tsn1!=NULL || u_data->assoc->sack1!=NULL)
660 u_data->io->max_y=u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
661 else
662 u_data->io->max_y= 0;
663 u_data->io->min_y = 0;
665 else
667 u_data->io->max_y = u_data->io->tmp_max_tsn1;
668 u_data->io->min_y = u_data->io->tmp_min_tsn1;
671 else if (u_data->dir==2)
673 if (u_data->io->tmp==FALSE)
675 if (u_data->assoc->tsn2!=NULL || u_data->assoc->sack2!=NULL)
676 u_data->io->max_y=u_data->io->tmp_max_tsn2 -u_data->io->tmp_min_tsn2;
677 else
678 u_data->io->max_y= 0;
679 u_data->io->min_y = 0;
681 else
683 u_data->io->max_y = u_data->io->tmp_max_tsn2;
684 u_data->io->min_y = u_data->io->tmp_min_tsn2;
688 #if GTK_CHECK_VERSION(2,22,0)
689 cr = cairo_create (u_data->io->surface);
690 #else
691 cr = gdk_cairo_create (u_data->io->pixmap);
692 #endif
693 cairo_set_source_rgb (cr, 1, 1, 1);
694 gtk_widget_get_allocation(u_data->io->draw_area, &widget_alloc);
695 cairo_rectangle (cr,
698 widget_alloc.width,
699 widget_alloc.height);
700 cairo_fill (cr);
701 cairo_destroy (cr);
703 /* x_axis */
704 #if GTK_CHECK_VERSION(2,22,0)
705 cr = cairo_create (u_data->io->surface);
706 #else
707 cr = gdk_cairo_create (u_data->io->pixmap);
708 #endif
709 cairo_set_line_width (cr, 1.0);
710 cairo_move_to(cr, LEFT_BORDER+u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);
711 cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);
713 cairo_move_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);
714 cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset - 5+0.5, u_data->io->surface_height - BOTTOM_BORDER - 5+0.5);
716 cairo_move_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset + 0.5, u_data->io->surface_height - BOTTOM_BORDER + 0.5);
717 cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset - 5.5, u_data->io->surface_height - BOTTOM_BORDER + 5.5);
718 cairo_stroke(cr);
719 cairo_destroy(cr);
721 u_data->io->axis_width=u_data->io->surface_width-LEFT_BORDER-RIGHT_BORDER-u_data->io->offset;
723 /* try to avoid dividing by zero */
724 if(u_data->io->tmp_width>0){
725 u_data->io->x_interval = (float)((u_data->io->axis_width*1.0)/u_data->io->tmp_width); /*distance in pixels between 2 data points*/
726 } else {
727 u_data->io->x_interval = (float)(u_data->io->axis_width);
730 e=0; /*number of decimals of x_interval*/
731 if (u_data->io->x_interval<1)
733 dis=1/u_data->io->x_interval;
734 while (dis >1)
736 dis/=10;
737 e++;
739 distance=1;
740 for (i=0; i<=e+1; i++)
741 distance*=10; /*distance per 100 pixels*/
743 else
744 distance=5;
746 g_snprintf(label_string, sizeof(label_string), "%d", 0);
747 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
748 layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
749 pango_layout_get_pixel_size(layout, &label_width, &label_height);
751 if (u_data->io->x1_tmp_usec==0)
752 sec=u_data->io->x1_tmp_sec;
753 else
754 sec=u_data->io->x1_tmp_sec+1;
757 if (u_data->io->offset!=0)
759 g_snprintf(label_string, sizeof(label_string), "%u", u_data->io->x1_tmp_sec);
761 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
762 pango_layout_set_text(layout, label_string, -1);
763 pango_layout_get_pixel_size(layout, &lwidth, NULL);
765 #if GTK_CHECK_VERSION(2,22,0)
766 cr = cairo_create (u_data->io->surface);
767 #else
768 cr = gdk_cairo_create (u_data->io->pixmap);
769 #endif
770 cairo_move_to (cr,
771 LEFT_BORDER-25,
772 u_data->io->surface_height-BOTTOM_BORDER+20);
773 pango_cairo_show_layout (cr, layout);
774 cairo_destroy (cr);
775 cr = NULL;
779 w=(guint32)(500/(guint32)(distance*u_data->io->x_interval)); /*there will be a label for every w_th tic*/
781 if (w==0)
782 w=1;
784 if (w==4 || w==3 || w==2)
786 w=5;
787 a=distance/10; /*distance between two tics*/
788 b = (guint32)((u_data->io->min_x/100000))%10; /* start for labels*/
790 else
792 a=distance/5;
793 b=0;
797 if (!u_data->io->uoff)
799 if (a>=1000000)
801 start=u_data->io->min_x/1000000*1000000;
802 if (a==1000000)
803 b = 0;
805 else
807 start=u_data->io->min_x/100000;
808 if (start%2!=0)
809 start--;
810 start*=100000;
811 b = (guint32)((start/100000))%10;
814 else
816 start = u_data->io->min_x;
817 if (start%2!=0)
818 start--;
819 b = 0;
823 for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
825 if (!u_data->io->uoff)
826 if (i>=u_data->io->min_x && i%1000000!=0)
828 length=5;
829 g_snprintf(label_string, sizeof(label_string), "%d", i%1000000);
830 if (j%w==0)
832 length=10;
833 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
834 pango_layout_set_text(layout, label_string, -1);
835 pango_layout_get_pixel_size(layout, &lwidth, NULL);
836 #if GTK_CHECK_VERSION(2,22,0)
837 cr = cairo_create (u_data->io->surface);
838 #else
839 cr = gdk_cairo_create (u_data->io->pixmap);
840 #endif
841 cairo_move_to (cr,
842 LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2,
843 u_data->io->surface_height-BOTTOM_BORDER+10);
844 pango_cairo_show_layout (cr, layout);
845 cairo_destroy (cr);
846 cr = NULL;
849 #if GTK_CHECK_VERSION(2,22,0)
850 cr = cairo_create (u_data->io->surface);
851 #else
852 cr = gdk_cairo_create (u_data->io->pixmap);
853 #endif
854 cairo_set_line_width (cr, 1.0);
855 cairo_move_to(cr,
856 LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
857 u_data->io->surface_height - BOTTOM_BORDER + 0.5);
858 cairo_line_to(cr,
859 LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
860 u_data->io->surface_height - BOTTOM_BORDER + length + 0.5);
861 cairo_stroke(cr);
862 cairo_destroy(cr);
865 if (!u_data->io->uoff)
867 if (i%1000000==0 && j%w==0)
869 sec=i/1000000;
870 write_label = TRUE;
873 else
875 if (j%w == 0)
877 sec = i;
878 write_label = TRUE;
881 if (write_label)
883 #if GTK_CHECK_VERSION(2,22,0)
884 cr = cairo_create (u_data->io->surface);
885 #else
886 cr = gdk_cairo_create (u_data->io->pixmap);
887 #endif
888 cairo_set_line_width (cr, 1.0);
889 cairo_move_to(cr,
890 LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
891 u_data->io->surface_height - BOTTOM_BORDER + 0.5);
892 cairo_line_to(cr,
893 LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
894 u_data->io->surface_height - BOTTOM_BORDER + 10 + 0.5);
895 cairo_stroke(cr);
896 cairo_destroy(cr);
898 g_snprintf(label_string, sizeof(label_string), "%d", sec);
899 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
900 pango_layout_set_text(layout, label_string, -1);
901 pango_layout_get_pixel_size(layout, &lwidth, NULL);
903 #if GTK_CHECK_VERSION(2,22,0)
904 cr = cairo_create (u_data->io->surface);
905 #else
906 cr = gdk_cairo_create (u_data->io->pixmap);
907 #endif
908 cairo_move_to (cr,
909 LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-10,
910 u_data->io->surface_height-BOTTOM_BORDER+20);
911 pango_cairo_show_layout (cr, layout);
912 cairo_destroy (cr);
913 cr = NULL;
915 write_label = FALSE;
920 g_strlcpy(label_string, "sec", sizeof(label_string));
922 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
923 pango_layout_set_text(layout, label_string, -1);
924 pango_layout_get_pixel_size(layout, &lwidth, NULL);
925 #if GTK_CHECK_VERSION(2,22,0)
926 cr = cairo_create (u_data->io->surface);
927 #else
928 cr = gdk_cairo_create (u_data->io->pixmap);
929 #endif
930 cairo_move_to (cr,
931 u_data->io->surface_width-RIGHT_BORDER-10,
932 u_data->io->surface_height-BOTTOM_BORDER+30);
933 pango_cairo_show_layout (cr, layout);
934 cairo_destroy (cr);
935 cr = NULL;
938 distance=5;
940 /* y-axis */
941 #if GTK_CHECK_VERSION(2,22,0)
942 cr = cairo_create (u_data->io->surface);
943 #else
944 cr = gdk_cairo_create (u_data->io->pixmap);
945 #endif
946 cairo_set_line_width (cr, 1.0);
947 cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
948 cairo_line_to(cr, LEFT_BORDER + 0.5, u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset + 0.5);
950 cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
951 cairo_line_to(cr, LEFT_BORDER - 5 + 0.5, TOP_BORDER - u_data->io->offset + 5 + 0.5);
953 cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
954 cairo_line_to(cr, LEFT_BORDER +5 + 0.5, TOP_BORDER - u_data->io->offset + 5 + 0.5);
955 cairo_stroke(cr);
956 cairo_destroy(cr);
958 u_data->io->y_interval = (float)(((u_data->io->surface_height-TOP_BORDER-BOTTOM_BORDER)*1.0)/(u_data->io->max_y-u_data->io->min_y));
960 e=0;
961 if (u_data->io->y_interval<1)
963 dis=1/u_data->io->y_interval;
964 while (dis >1)
966 dis/=10;
967 e++;
969 distance=1;
970 for (i=0; i<=e; i++)
971 distance=distance*10;
973 else if (u_data->io->y_interval<2)
974 distance = 10;
976 if (u_data->io->max_y>0)
978 for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
980 if (i>=u_data->io->min_y)
982 length=5;
983 g_snprintf(label_string, sizeof(label_string), "%d", i);
984 if (i%distance==0 || (distance<=5 && u_data->io->y_interval>10))
986 length=10;
988 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
989 pango_layout_set_text(layout, label_string, -1);
990 pango_layout_get_pixel_size(layout, &lwidth, NULL);
991 #if GTK_CHECK_VERSION(2,22,0)
992 cr = cairo_create (u_data->io->surface);
993 #else
994 cr = gdk_cairo_create (u_data->io->pixmap);
995 #endif
996 cairo_move_to (cr,
997 LEFT_BORDER-length-lwidth-5,
998 u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-POINT_SIZE);
999 pango_cairo_show_layout (cr, layout);
1000 cairo_destroy (cr);
1001 cr = NULL;
1004 #if GTK_CHECK_VERSION(2,22,0)
1005 cr = cairo_create (u_data->io->surface);
1006 #else
1007 cr = gdk_cairo_create (u_data->io->pixmap);
1008 #endif
1009 cairo_set_line_width (cr, 1.0);
1010 cairo_move_to(cr,
1011 LEFT_BORDER - length + 0.5,
1012 u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval + 0.5);
1013 cairo_line_to(cr,
1014 LEFT_BORDER + 0.5,
1015 u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval + 0.5);
1016 cairo_stroke(cr);
1017 cairo_destroy(cr);
1022 else if ((u_data->dir==1 && u_data->assoc->n_array_tsn1==0) || (u_data->dir==2 && u_data->assoc->n_array_tsn2==0))
1023 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
1025 g_object_unref(G_OBJECT(layout));
1028 /* This function is used to change the title
1029 * in the graph dialogue to NR_SACK or SACK based on the
1030 * association
1031 * If an association has both SAKC and NR_SACK PDU's
1032 * a warning is popped
1034 static void
1035 updateLabels(void)
1037 if (gIsSackChunkPresent && gIsNRSackChunkPresent)
1039 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "This data set contains both SACK and NR SACK PDUs.");
1040 gtk_button_set_label( (GtkButton*) sack_bt, "Show both Sack and NR Sack");
1042 else if (gIsSackChunkPresent)
1043 gtk_button_set_label( (GtkButton*) sack_bt, "Show Only Sack");
1044 else
1045 /* gIsNRSackChunkPresent will be true here */
1046 gtk_button_set_label( (GtkButton*) sack_bt, "Show Only NR Sack");
1049 static void
1050 sctp_graph_redraw(struct sctp_udata *u_data)
1052 sctp_graph_t *ios;
1053 GtkAllocation widget_alloc;
1054 cairo_t *cr;
1056 u_data->io->needs_redraw=TRUE;
1058 sctp_graph_draw(u_data);
1059 switch (u_data->io->graph_type)
1061 case 0:
1062 /* Show both TSN and SACK information
1063 * Reset the global sack variable
1064 * for sack and nr sack cases
1066 gIsSackChunkPresent = 0;
1067 gIsNRSackChunkPresent = 0;
1068 draw_sack_graph(u_data);
1069 draw_nr_sack_graph(u_data);
1070 draw_tsn_graph(u_data);
1071 break;
1072 case 1:
1073 /* Show only TSN */
1074 draw_tsn_graph(u_data);
1075 break;
1076 case 2:
1077 /* Show only SACK information
1078 * Reset the global sack variable
1079 * for sack and nr sack cases
1081 gIsSackChunkPresent = 0;
1082 gIsNRSackChunkPresent = 0;
1083 draw_sack_graph(u_data);
1084 draw_nr_sack_graph(u_data);
1085 break;
1088 /* Updates the sack / nr sack buttons */
1089 updateLabels();
1091 ios=(sctp_graph_t *)g_object_get_data(G_OBJECT(u_data->io->draw_area), "sctp_graph_t");
1092 g_assert(ios != NULL);
1094 cr = gdk_cairo_create (gtk_widget_get_window(u_data->io->draw_area));
1096 #if GTK_CHECK_VERSION(2,22,0)
1097 cairo_set_source_surface (cr, ios->surface, 0, 0);
1098 #else
1099 gdk_cairo_set_source_pixmap (cr, ios->pixmap, 0, 0);
1100 #endif
1101 gtk_widget_get_allocation(u_data->io->draw_area, &widget_alloc);
1102 cairo_rectangle (cr, 0, 0, widget_alloc.width, widget_alloc.height);
1103 cairo_fill (cr);
1105 cairo_destroy (cr);
1109 static void
1110 on_sack_bt(GtkWidget *widget _U_, gpointer user_data)
1112 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1114 u_data->io->graph_type=2;
1115 sctp_graph_redraw(u_data);
1118 static void
1119 on_tsn_bt(GtkWidget *widget _U_, gpointer user_data)
1121 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1123 u_data->io->graph_type=1;
1124 sctp_graph_redraw(u_data);
1127 static void
1128 on_both_bt(GtkWidget *widget _U_, gpointer user_data)
1130 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1132 u_data->io->graph_type=0;
1133 sctp_graph_redraw(u_data);
1136 static void
1137 sctp_graph_close_cb(GtkWidget* widget _U_, gpointer user_data)
1139 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1141 gtk_grab_remove(GTK_WIDGET(u_data->io->window));
1142 gtk_widget_destroy(GTK_WIDGET(u_data->io->window));
1146 static gboolean
1147 configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, gpointer user_data)
1149 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1150 GtkAllocation widget_alloc;
1151 cairo_t *cr;
1153 g_assert(u_data->io != NULL);
1155 #if GTK_CHECK_VERSION(2,22,0)
1156 if(u_data->io->surface){
1157 cairo_surface_destroy (u_data->io->surface);
1158 u_data->io->surface=NULL;
1160 gtk_widget_get_allocation(widget, &widget_alloc);
1161 u_data->io->surface = gdk_window_create_similar_surface (gtk_widget_get_window(widget),
1162 CAIRO_CONTENT_COLOR,
1163 widget_alloc.width,
1164 widget_alloc.height);
1165 #else
1166 if(u_data->io->pixmap){
1167 g_object_unref(u_data->io->pixmap);
1168 u_data->io->pixmap=NULL;
1170 gtk_widget_get_allocation(widget, &widget_alloc);
1171 u_data->io->pixmap=gdk_pixmap_new(gtk_widget_get_window(widget),
1172 widget_alloc.width,
1173 widget_alloc.height,
1174 -1);
1175 #endif
1177 u_data->io->surface_width=widget_alloc.width;
1178 u_data->io->surface_height=widget_alloc.height;
1180 #if GTK_CHECK_VERSION(2,22,0)
1181 cr = cairo_create (u_data->io->surface);
1182 #else
1183 cr = gdk_cairo_create (u_data->io->pixmap);
1184 #endif
1185 cairo_rectangle (cr, 0, 0, widget_alloc.width, widget_alloc.height);
1186 cairo_set_source_rgb (cr, 1, 1, 1);
1187 cairo_fill (cr);
1188 cairo_destroy (cr);
1190 sctp_graph_redraw(u_data);
1191 return TRUE;
1194 #if GTK_CHECK_VERSION(3,0,0)
1195 static gboolean
1196 draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data)
1198 sctp_graph_t *ios = (sctp_graph_t *)user_data;
1199 GtkAllocation allocation;
1201 gtk_widget_get_allocation (widget, &allocation);
1202 cairo_set_source_surface (cr, ios->surface, 0, 0);
1203 cairo_rectangle (cr, 0, 0, allocation.width, allocation.width);
1204 cairo_fill (cr);
1206 return FALSE;
1208 #else
1209 static gboolean
1210 expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
1212 sctp_graph_t *ios = (sctp_graph_t *)user_data;
1213 cairo_t *cr;
1215 g_assert(ios != NULL);
1217 cr = gdk_cairo_create (gtk_widget_get_window(widget));
1219 #if GTK_CHECK_VERSION(2,22,0)
1220 cairo_set_source_surface (cr, ios->surface, 0, 0);
1221 #else
1222 gdk_cairo_set_source_pixmap (cr, ios->pixmap, 0, 0);
1223 #endif
1224 cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
1225 cairo_fill (cr);
1227 cairo_destroy (cr);
1229 return FALSE;
1231 #endif
1233 static void
1234 on_zoomin_bt (GtkWidget *widget _U_, gpointer user_data)
1236 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1237 sctp_min_max_t *tmp_minmax;
1239 if (u_data->io->rectangle_present==TRUE)
1241 tmp_minmax = (sctp_min_max_t *)g_malloc(sizeof(sctp_min_max_t));
1243 u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
1244 u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
1245 u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
1246 u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
1247 tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
1248 tmp_minmax->tmp_min_usecs= u_data->io->x1_tmp_usec;
1249 tmp_minmax->tmp_max_secs= u_data->io->x2_tmp_sec;
1250 tmp_minmax->tmp_max_usecs= u_data->io->x2_tmp_usec;
1251 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
1252 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
1253 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
1254 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
1255 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1256 u_data->io->length = g_slist_length(u_data->assoc->min_max);
1257 u_data->io->tmp=TRUE;
1258 u_data->io->rectangle=FALSE;
1259 u_data->io->rectangle_present=FALSE;
1260 gtk_widget_set_sensitive(zoomout_bt, TRUE);
1261 sctp_graph_redraw(u_data);
1263 else
1265 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Please draw a rectangle around the area you want to zoom in.");
1269 static void
1270 zoomin_bt_fcn (struct sctp_udata *u_data)
1272 sctp_min_max_t *tmp_minmax;
1274 tmp_minmax = (sctp_min_max_t *)g_malloc(sizeof(sctp_min_max_t));
1276 u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
1277 u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
1278 u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
1279 u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
1280 tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
1281 tmp_minmax->tmp_min_usecs= u_data->io->x1_tmp_usec;
1282 tmp_minmax->tmp_max_secs= u_data->io->x2_tmp_sec;
1283 tmp_minmax->tmp_max_usecs= u_data->io->x2_tmp_usec;
1284 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
1285 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
1286 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
1287 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
1288 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1289 u_data->io->length = g_slist_length(u_data->assoc->min_max);
1290 u_data->io->tmp=TRUE;
1291 u_data->io->rectangle=FALSE;
1292 u_data->io->rectangle_present=FALSE;
1293 gtk_widget_set_sensitive(zoomout_bt, TRUE);
1294 sctp_graph_redraw(u_data);
1300 static void
1301 on_zoomout_bt (GtkWidget *widget _U_, gpointer user_data)
1303 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1304 sctp_min_max_t *tmp_minmax, *mm;
1305 gint l;
1307 l = g_slist_length(u_data->assoc->min_max);
1309 if (u_data->assoc->min_max!=NULL)
1311 mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
1312 u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
1313 g_free(mm);
1314 if (l>2)
1316 tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
1317 u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
1318 u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
1319 u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
1320 u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
1321 u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
1322 u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
1323 u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
1324 u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
1325 u_data->io->tmp=TRUE;
1327 else
1329 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1330 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1331 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1332 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1333 u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
1334 u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
1335 u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
1336 u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
1337 u_data->io->tmp=FALSE;
1340 else
1342 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1343 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1344 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1345 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1346 u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
1347 u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
1348 u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
1349 u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
1350 u_data->io->tmp=FALSE;
1352 if (g_slist_length(u_data->assoc->min_max)==1)
1353 gtk_widget_set_sensitive(zoomout_bt, FALSE);
1354 sctp_graph_redraw(u_data);
1357 static gboolean
1358 on_button_press_event (GtkWidget *widget _U_, GdkEventButton *event, gpointer user_data)
1360 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1361 sctp_graph_t *ios;
1362 cairo_t *cr;
1364 if (u_data->io->rectangle==TRUE)
1366 #if GTK_CHECK_VERSION(2,22,0)
1367 cr = cairo_create (u_data->io->surface);
1368 #else
1369 cr = gdk_cairo_create (u_data->io->pixmap);
1370 #endif
1371 cairo_rectangle (cr,
1372 floor(MIN(u_data->io->x_old,u_data->io->x_new)),
1373 floor(MIN(u_data->io->y_old,u_data->io->y_new)),
1374 floor(abs((int)(u_data->io->x_new-u_data->io->x_old))),
1375 floor(abs((int)(u_data->io->y_new-u_data->io->y_old))));
1376 cairo_set_source_rgb (cr, 1, 1, 1);
1377 cairo_stroke (cr);
1378 cairo_destroy (cr);
1380 ios=(sctp_graph_t *)g_object_get_data(G_OBJECT(u_data->io->draw_area), "sctp_graph_t");
1382 g_assert(ios != NULL);
1384 cr = gdk_cairo_create (gtk_widget_get_window(u_data->io->draw_area));
1386 #if GTK_CHECK_VERSION(2,22,0)
1387 cairo_set_source_surface (cr, ios->surface, 0, 0);
1388 #else
1389 gdk_cairo_set_source_pixmap (cr, ios->pixmap, 0, 0);
1390 #endif
1391 cairo_rectangle (cr, 0, 0, abs((int)(u_data->io->x_new-u_data->io->x_old)), abs((int)(u_data->io->y_new-u_data->io->y_old)));
1392 cairo_fill (cr);
1394 cairo_destroy (cr);
1396 sctp_graph_redraw(u_data);
1398 u_data->io->x_old=event->x;
1399 u_data->io->y_old=event->y;
1400 if (u_data->io->y_old>u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-POINT_SIZE)
1401 u_data->io->y_old=u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-POINT_SIZE;
1402 if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
1403 u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
1404 u_data->io->rectangle=FALSE;
1406 return TRUE;
1410 static gboolean
1411 on_button_release_event (GtkWidget *widget _U_, GdkEventButton *event, gpointer user_data)
1413 struct sctp_udata *u_data = (struct sctp_udata *)user_data;
1414 sctp_graph_t *ios;
1415 guint32 helpx, helpy, x1_tmp, x2_tmp, y_value, t_size=0, s_size=0, i, y_tolerance;
1416 gint label_width, label_height;
1417 gdouble x_value, position, s_diff=0, t_diff=0, x_tolerance=0.0001;
1418 gint lwidth;
1419 char label_string[30];
1420 GPtrArray *tsnlist = NULL, *sacklist=NULL;
1421 struct tsn_sort *tsn, *sack=NULL;
1422 gboolean sack_found = FALSE;
1423 GtkAllocation widget_alloc;
1424 PangoLayout *layout;
1425 cairo_t *cr;
1427 g_snprintf(label_string, 15, "%d", 0);
1428 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
1429 layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
1430 pango_layout_get_pixel_size(layout, &label_width, &label_height);
1432 if (event->y>u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset)
1433 event->y = u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset;
1434 if (event->x < LEFT_BORDER+u_data->io->offset)
1435 event->x = LEFT_BORDER+u_data->io->offset;
1436 if (abs((int)(event->x-u_data->io->x_old))>10 || abs((int)(event->y-u_data->io->y_old))>10)
1438 u_data->io->rect_x_min = (gint)floor(MIN(u_data->io->x_old,event->x));
1439 u_data->io->rect_x_max = (gint)ceil(MAX(u_data->io->x_old,event->x));
1440 u_data->io->rect_y_min = (gint)floor(MIN(u_data->io->y_old,event->y));
1441 u_data->io->rect_y_max = (gint)ceil(MAX(u_data->io->y_old,event->y))+POINT_SIZE;
1442 #if GTK_CHECK_VERSION(2,22,0)
1443 cr = cairo_create (u_data->io->surface);
1444 #else
1445 cr = gdk_cairo_create (u_data->io->pixmap);
1446 #endif
1447 cairo_rectangle (cr,
1448 u_data->io->rect_x_min+0.5,
1449 u_data->io->rect_y_min+0.5,
1450 u_data->io->rect_x_max - u_data->io->rect_x_min,
1451 u_data->io->rect_y_max - u_data->io->rect_y_min);
1452 cairo_set_line_width (cr, 1.0);
1453 cairo_stroke (cr);
1454 cairo_destroy (cr);
1456 ios=(sctp_graph_t *)g_object_get_data(G_OBJECT(u_data->io->draw_area), "sctp_graph_t");
1458 g_assert(ios != NULL);
1460 cr = gdk_cairo_create (gtk_widget_get_window(u_data->io->draw_area));
1462 #if GTK_CHECK_VERSION(2,22,0)
1463 cairo_set_source_surface (cr, ios->surface, 0, 0);
1464 #else
1465 gdk_cairo_set_source_pixmap (cr, ios->pixmap, 0, 0);
1466 #endif
1467 gtk_widget_get_allocation(u_data->io->draw_area, &widget_alloc);
1468 cairo_rectangle (cr, 0, 0, widget_alloc.width, widget_alloc.height);
1469 cairo_fill (cr);
1471 cairo_destroy (cr);
1473 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));
1474 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));
1475 helpx=MIN(x1_tmp, x2_tmp);
1476 if (helpx==x2_tmp)
1478 x2_tmp=x1_tmp;
1479 x1_tmp=helpx;
1481 if (u_data->io->uoff)
1483 if (x2_tmp - x1_tmp <= 1500)
1484 u_data->io->uoff = FALSE;
1485 u_data->io->x1_tmp_sec=(guint32)x1_tmp;
1486 u_data->io->x1_tmp_usec=0;
1487 u_data->io->x2_tmp_sec=(guint32)x2_tmp;
1488 u_data->io->x2_tmp_usec=0;
1490 else
1492 u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
1493 u_data->io->x1_tmp_usec=x1_tmp%1000000;
1494 u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
1495 u_data->io->x2_tmp_usec=x2_tmp%1000000;
1497 u_data->io->x1_akt_sec = u_data->io->x1_tmp_sec;
1498 u_data->io->x1_akt_usec = u_data->io->x1_tmp_usec;
1499 u_data->io->x2_akt_sec = u_data->io->x2_tmp_sec;
1500 u_data->io->x2_akt_usec = u_data->io->x2_tmp_usec;
1502 u_data->io->y1_tmp=(guint32)((u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-u_data->io->y_old)/u_data->io->y_interval);
1503 u_data->io->y2_tmp=(guint32)((u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-event->y)/u_data->io->y_interval);
1504 helpy = MIN(u_data->io->y1_tmp, u_data->io->y2_tmp);
1505 u_data->io->y2_tmp = MAX(u_data->io->y1_tmp, u_data->io->y2_tmp);
1506 u_data->io->y1_tmp = helpy;
1507 u_data->io->x_new=event->x;
1508 u_data->io->y_new=event->y;
1509 u_data->io->rectangle=TRUE;
1510 u_data->io->rectangle_present=TRUE;
1512 else
1514 if (u_data->io->rectangle_present==TRUE)
1516 u_data->io->rectangle_present=FALSE;
1517 if (event->x >= u_data->io->rect_x_min && event->x <= u_data->io->rect_x_max &&
1518 event->y >= u_data->io->rect_y_min && event->y <= u_data->io->rect_y_max)
1519 zoomin_bt_fcn(u_data);
1520 else
1522 u_data->io->x1_tmp_sec = u_data->io->x1_akt_sec;
1523 u_data->io->x1_tmp_usec = u_data->io->x1_akt_usec;
1524 u_data->io->x2_tmp_sec = u_data->io->x2_akt_sec;
1525 u_data->io->x2_tmp_usec = u_data->io->x2_akt_usec;
1526 sctp_graph_redraw(u_data);
1529 else if (label_set)
1531 label_set = FALSE;
1532 sctp_graph_redraw(u_data);
1534 else
1536 x_value = ((event->x-LEFT_BORDER-u_data->io->offset) * ((u_data->io->x2_tmp_sec+u_data->io->x2_tmp_usec/1000000.0)-(u_data->io->x1_tmp_sec+u_data->io->x1_tmp_usec/1000000.0)) / (u_data->io->surface_width-LEFT_BORDER-RIGHT_BORDER-u_data->io->offset))+u_data->io->x1_tmp_sec+u_data->io->x1_tmp_usec/1000000.0;
1537 y_value = (gint)rint((u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-event->y) * (max_tsn - min_tsn) / (u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset)) + min_tsn;
1539 if (u_data->dir == 1)
1541 tsnlist = u_data->assoc->sort_tsn1;
1542 t_size = u_data->assoc->n_data_chunks_ep1;
1543 sacklist = u_data->assoc->sort_sack1;
1544 s_size = u_data->assoc->n_sack_chunks_ep1;
1546 else
1548 tsnlist = u_data->assoc->sort_tsn2;
1549 t_size = u_data->assoc->n_data_chunks_ep2;
1550 sacklist = u_data->assoc->sort_sack2;
1551 s_size = u_data->assoc->n_sack_chunks_ep2;
1553 x_tolerance = (gdouble)((u_data->io->tmp_width / u_data->io->axis_width*1.0))*5/1000000.0;
1554 y_tolerance = (guint32)(((u_data->io->max_y - u_data->io->min_y) / (u_data->io->surface_height-TOP_BORDER-BOTTOM_BORDER-u_data->io->offset)) * 2.0);
1555 if (y_tolerance==0)
1556 y_tolerance = 2;
1557 else if (y_tolerance > 5)
1558 y_tolerance = 5;
1560 for (i=0; i<s_size; i++)
1562 sack = (struct tsn_sort*)(g_ptr_array_index(sacklist, i));
1563 if ((guint32)abs(sack->tsnumber - y_value)<y_tolerance)
1565 s_diff = fabs((sack->secs+sack->usecs/1000000.0)- x_value);
1566 if (s_diff < x_tolerance)
1567 sack_found = TRUE;
1568 break;
1572 for (i=0; i<t_size; i++)
1574 tsn = (struct tsn_sort*)(g_ptr_array_index(tsnlist, i));
1575 if ((guint32)abs(tsn->tsnumber - y_value)<y_tolerance)
1577 t_diff = fabs((tsn->secs+tsn->usecs/1000000.0)- x_value);
1578 if (sack_found && s_diff < t_diff)
1580 cf_goto_frame(&cfile, sack->framenumber);
1581 x_value = sack->secs+sack->usecs/1000000.0;
1582 y_value = sack->tsnumber;
1584 else if (t_diff < x_tolerance)
1586 cf_goto_frame(&cfile, tsn->framenumber);
1587 x_value = tsn->secs+tsn->usecs/1000000.0;
1588 y_value = tsn->tsnumber;
1590 break;
1594 g_snprintf(label_string, sizeof(label_string), "(%.6lf, %u)", x_value, y_value);
1596 label_set = TRUE;
1598 #if GTK_CHECK_VERSION(2,22,0)
1599 cr = cairo_create (u_data->io->surface);
1600 #else
1601 cr = gdk_cairo_create (u_data->io->pixmap);
1602 #endif
1603 cairo_set_line_width (cr, 1.0);
1604 cairo_move_to(cr,
1605 (event->x-2)+0.5,
1606 (event->y)+0.5);
1607 cairo_line_to(cr,
1608 (event->x+2)+0.5,
1609 (event->y)+0.5);
1610 cairo_stroke(cr);
1611 cairo_destroy(cr);
1613 #if GTK_CHECK_VERSION(2,22,0)
1614 cr = cairo_create (u_data->io->surface);
1615 #else
1616 cr = gdk_cairo_create (u_data->io->pixmap);
1617 #endif
1618 cairo_set_line_width (cr, 1.0);
1619 cairo_move_to(cr,
1620 (event->x)+0.5,
1621 (event->y-2)+0.5);
1622 cairo_line_to(cr,
1623 (event->x)+0.5,
1624 (event->y+2)+0.5);
1625 cairo_stroke(cr);
1626 cairo_destroy(cr);
1628 if (event->x+150>=u_data->io->surface_width)
1629 position = event->x - 150;
1630 else
1631 position = event->x + 5;
1634 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
1635 pango_layout_set_text(layout, label_string, -1);
1636 pango_layout_get_pixel_size(layout, &lwidth, NULL);
1638 #if GTK_CHECK_VERSION(2,22,0)
1639 cr = cairo_create (u_data->io->surface);
1640 #else
1641 cr = gdk_cairo_create (u_data->io->pixmap);
1642 #endif
1643 cairo_move_to (cr,
1644 position,
1645 event->y-10);
1646 pango_cairo_show_layout (cr, layout);
1647 cairo_destroy (cr);
1648 cr = NULL;
1650 ios=(sctp_graph_t *)g_object_get_data(G_OBJECT(u_data->io->draw_area), "sctp_graph_t");
1651 g_assert(ios != NULL);
1653 cr = gdk_cairo_create (gtk_widget_get_window(u_data->io->draw_area));
1655 #if GTK_CHECK_VERSION(2,22,0)
1656 cairo_set_source_surface (cr, ios->surface, 0, 0);
1657 #else
1658 gdk_cairo_set_source_pixmap (cr, ios->pixmap, 0, 0);
1659 #endif
1660 gtk_widget_get_allocation(u_data->io->draw_area, &widget_alloc);
1661 cairo_rectangle (cr, 0, 0, widget_alloc.width, widget_alloc.height);
1662 cairo_fill (cr);
1664 cairo_destroy (cr);
1668 g_object_unref(G_OBJECT(layout));
1670 return TRUE;
1674 static void
1675 init_sctp_graph_window(struct sctp_udata *u_data)
1677 GtkWidget *vbox;
1678 GtkWidget *hbox;
1679 GtkWidget *bt_close, *tsn_bt, *both_bt, *zoomin_bt;
1681 /* create the main window */
1682 u_data->io->window= dlg_window_new("WSCTP Graphics"); /* transient_for top_level */
1683 gtk_window_set_destroy_with_parent (GTK_WINDOW(u_data->io->window), TRUE);
1685 vbox=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 0, FALSE);
1686 gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
1687 gtk_widget_show(vbox);
1689 create_draw_area(vbox, u_data);
1691 sctp_graph_set_title(u_data);
1693 hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
1694 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1695 gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
1696 gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
1697 gtk_box_set_spacing(GTK_BOX (hbox), 0);
1698 gtk_widget_show(hbox);
1699 sack_bt = gtk_button_new_with_label ("Show Only Sacks");
1700 gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
1701 gtk_widget_show(sack_bt);
1702 g_signal_connect(sack_bt, "clicked", G_CALLBACK(on_sack_bt), u_data);
1704 tsn_bt = gtk_button_new_with_label ("Show Only TSNs");
1705 gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
1706 gtk_widget_show(tsn_bt);
1707 g_signal_connect(tsn_bt, "clicked", G_CALLBACK(on_tsn_bt), u_data);
1709 both_bt = gtk_button_new_with_label ("Show both");
1710 gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
1711 gtk_widget_show(both_bt);
1712 g_signal_connect(both_bt, "clicked", G_CALLBACK(on_both_bt), u_data);
1714 zoomin_bt = gtk_button_new_with_label ("Zoom in");
1715 gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
1716 gtk_widget_show(zoomin_bt);
1717 g_signal_connect(zoomin_bt, "clicked", G_CALLBACK(on_zoomin_bt), u_data);
1718 gtk_widget_set_tooltip_text(zoomin_bt, "Zoom in the area you have selected");
1720 zoomout_bt = gtk_button_new_with_label ("Zoom out");
1721 gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
1722 gtk_widget_show(zoomout_bt);
1723 g_signal_connect(zoomout_bt, "clicked", G_CALLBACK(on_zoomout_bt), u_data);
1724 gtk_widget_set_tooltip_text(zoomout_bt, "Zoom out one step");
1725 gtk_widget_set_sensitive(zoomout_bt, FALSE);
1727 bt_close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
1728 gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
1729 gtk_widget_show(bt_close);
1730 g_signal_connect(bt_close, "clicked", G_CALLBACK(sctp_graph_close_cb), u_data);
1732 g_signal_connect(u_data->io->draw_area,"button_press_event",G_CALLBACK(on_button_press_event), u_data);
1733 g_signal_connect(u_data->io->draw_area,"button_release_event",G_CALLBACK(on_button_release_event), u_data);
1734 gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
1736 gtk_widget_show(u_data->io->window);
1739 static void
1740 sctp_graph_set_title(struct sctp_udata *u_data)
1742 char *display_name;
1743 char *title;
1745 if(!u_data->io->window)
1747 return;
1749 display_name = cf_get_display_name(&cfile);
1750 title = g_strdup_printf("SCTP TSNs and Sacks over Time: %s Port1 %u Port2 %u Endpoint %u",
1751 display_name, u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
1752 g_free(display_name);
1753 gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
1754 g_free(title);
1757 static void
1758 gtk_sctpgraph_init(struct sctp_udata *u_data)
1760 sctp_graph_t *io;
1761 sctp_min_max_t* tmp_minmax;
1763 io=(sctp_graph_t *)g_malloc(sizeof(sctp_graph_t));
1764 io->needs_redraw=TRUE;
1765 io->x_interval=1000;
1766 io->window=NULL;
1767 io->draw_area=NULL;
1768 #if GTK_CHECK_VERSION(2,22,0)
1769 io->surface=NULL;
1770 #else
1771 io->pixmap=NULL;
1772 #endif
1773 io->surface_width=800;
1774 io->surface_height=600;
1775 io->graph_type=0;
1776 u_data->io=io;
1777 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1778 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1779 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1780 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1781 u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
1782 u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
1783 u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
1784 u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
1785 u_data->io->tmp=FALSE;
1787 tmp_minmax = (sctp_min_max_t *)g_malloc(sizeof(sctp_min_max_t));
1788 tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
1789 tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
1790 tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
1791 tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
1792 tmp_minmax->tmp_min_tsn2=u_data->assoc->min_tsn2;
1793 tmp_minmax->tmp_min_tsn1=u_data->assoc->min_tsn1;
1794 tmp_minmax->tmp_max_tsn1=u_data->assoc->max_tsn1;
1795 tmp_minmax->tmp_max_tsn2=u_data->assoc->max_tsn2;
1796 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1798 /* build the GUI */
1799 init_sctp_graph_window(u_data);
1800 sctp_graph_redraw(u_data);
1805 static void
1806 quit(GObject *object _U_, gpointer user_data)
1808 struct sctp_udata *u_data=(struct sctp_udata *)user_data;
1810 decrease_childcount(u_data->parent);
1811 remove_child(u_data, u_data->parent);
1813 g_free(u_data->io);
1815 u_data->assoc->min_max = NULL;
1816 g_free(u_data);
1820 static void
1821 create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
1824 u_data->io->draw_area=gtk_drawing_area_new();
1825 g_object_set_data(G_OBJECT(u_data->io->draw_area), "sctp_graph_t", u_data->io);
1826 g_signal_connect(u_data->io->draw_area, "destroy", G_CALLBACK(quit), u_data);
1828 gtk_widget_set_size_request(u_data->io->draw_area, u_data->io->surface_width, u_data->io->surface_height);
1830 /* signals needed to handle backing pixmap */
1831 #if GTK_CHECK_VERSION(3,0,0)
1832 g_signal_connect(u_data->io->draw_area, "draw", G_CALLBACK(draw_event), u_data->io);
1833 #else
1834 g_signal_connect(u_data->io->draw_area, "expose_event", G_CALLBACK(expose_event), u_data->io);
1835 #endif
1836 g_signal_connect(u_data->io->draw_area, "configure_event", G_CALLBACK(configure_event), u_data);
1838 gtk_widget_show(u_data->io->draw_area);
1839 gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
1844 void
1845 create_graph(guint16 dir, struct sctp_analyse* userdata)
1847 struct sctp_udata *u_data;
1849 u_data=(struct sctp_udata *)g_malloc(sizeof(struct sctp_udata));
1850 u_data->assoc=userdata->assoc;
1851 u_data->io=NULL;
1852 u_data->dir = dir;
1853 u_data->parent = userdata;
1854 if ((u_data->dir==1 && u_data->assoc->n_array_tsn1==0)|| (u_data->dir==2 && u_data->assoc->n_array_tsn2==0))
1855 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
1856 else
1858 set_child(u_data, u_data->parent);
1859 increase_childcount(u_data->parent);
1860 gtk_sctpgraph_init(u_data);
1864 #if defined(_WIN32) && !defined(__MINGW32__) && (_MSC_VER < 1800)
1865 /* Starting VS2013, rint already defined in math.h. No need to redefine */
1866 /* replacement of Unix rint() for Windows */
1867 static int
1868 rint (double x)
1870 char *buf;
1871 int i,dec,sig;
1873 buf = _fcvt(x, 0, &dec, &sig);
1874 i = atoi(buf);
1875 if(sig == 1) {
1876 i = i * -1;
1878 return(i);
1880 #endif