+/*
+ * This function plots the NR_SACK gap ack and
+ * nr gap acks.
+ * Red dot - Cumulative TSN ack
+ * Green dot - Gap ack
+ * Blue circle - NR Gap ack
+ */
+static void
+draw_nr_sack_graph(struct sctp_udata *u_data)
+{
+ tsn_t *sack;
+ GList *list=NULL, *tlist;
+ guint16 gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps;
+ guint8 type;
+ guint32 tsnumber, j;
+ gint xvalue, yvalue;
+ GdkColor red_color = {0, 65535, 0, 0};
+ GdkColor blue_color = {0, 0, 0, 65535};
+ GdkColor green_color = {0, 0, 65535, 0};
+ GdkGC *red_gc, *blue_gc, *green_gc;
+ struct nr_sack_chunk_header *nr_sack_header;
+ struct gaps *nr_gap;
+ guint32 max_num, diff;
+ /* This holds the sum of gap acks and nr gap acks */
+ guint16 total_gaps = 0;
+
+ red_gc = gdk_gc_new(u_data->io->draw_area->window);
+ gdk_gc_set_rgb_fg_color(red_gc, &red_color);
+ blue_gc = gdk_gc_new(u_data->io->draw_area->window);
+ gdk_gc_set_rgb_fg_color(blue_gc, &blue_color);
+ green_gc = gdk_gc_new(u_data->io->draw_area->window);
+ gdk_gc_set_rgb_fg_color(green_gc, &green_color);
+
+
+ if (u_data->dir==2)
+ {
+ list = g_list_last(u_data->assoc->sack2);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn2;
+ max_tsn=u_data->assoc->max_tsn2;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
+ max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
+ }
+ }
+ else if (u_data->dir==1)
+ {
+ list = g_list_last(u_data->assoc->sack1);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn1;
+ max_tsn=u_data->assoc->max_tsn1;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
+ max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
+ }
+ }
+ while (list)
+ {
+ sack = (tsn_t*) (list->data);
+ tlist = g_list_first(sack->tsns);
+ while (tlist)
+ {
+ type = ((struct chunk_header *)tlist->data)->type;
+ /*
+ * The tlist->data is memcpy ied to the appropriate structure
+ * They entire raw tvb bytes are copied on to one of the *_chunk_header
+ * structures in sctp_stat.c
+ */
+ if (type == SCTP_NR_SACK_CHUNK_ID)
+ {
+ gIsNRSackChunkPresent = 1;
+ nr_sack_header =(struct nr_sack_chunk_header *)tlist->data;
+ numberOf_nr_gaps=g_ntohs(nr_sack_header->nr_of_nr_gaps);
+ numberOf_gaps=g_ntohs(nr_sack_header->nr_of_gaps);
+ tsnumber = g_ntohl(nr_sack_header->cum_tsn_ack);
+ total_gaps = numberOf_gaps + numberOf_nr_gaps;
+ if (sack->secs>=u_data->io->x1_tmp_sec)
+ {
+ /* If the number of nr_gaps is greater than 0 */
+ if ( total_gaps > 0 )
+ {
+ nr_gap = &nr_sack_header->gaps[0];
+ for ( i=0; i < total_gaps; i++ )
+ {
+ gap_start=g_ntohs(nr_gap->start);
+ gap_end = g_ntohs(nr_gap->end);
+ max_num= gap_end + tsnumber;
+ for ( j = gap_start; j <= gap_end; j++)
+ {
+ if (u_data->io->uoff)
+ diff = sack->secs - u_data->io->min_x;
+ else
+ diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
+ xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
+ yvalue = (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-POINT_SIZE-u_data->io->offset-((SUB_32(j+tsnumber,min_tsn))*u_data->io->y_interval));
+ if (xvalue >= LEFT_BORDER+u_data->io->offset &&
+ xvalue <= u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset &&
+ yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
+ yvalue <= u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ {
+ /* Check if this is an GAP ACK or NR GAP ACK */
+ if ( i >= numberOf_gaps)
+ {
+ /* This is a nr gap ack */
+ gdk_draw_arc(u_data->io->pixmap,blue_gc,FALSE,
+ xvalue,
+ yvalue,
+ POINT_SIZE , POINT_SIZE,0, (64*360) );
+
+ /* All NR GAP Acks are also gap acks, so plot these as
+ * gap acks - green dot.
+ * These will be shown as points with a green dot - GAP ACK
+ * surrounded by a blue circle - NR GAP ack
+ */
+ gdk_draw_arc(u_data->io->pixmap, green_gc, TRUE,
+ xvalue,
+ yvalue,
+ POINT_SIZE , POINT_SIZE,0, (64*360) );
+
+ }
+ else
+ {
+ /* This is just a gap ack */
+ gdk_draw_arc(u_data->io->pixmap, green_gc, TRUE,
+ xvalue,
+ yvalue,
+ POINT_SIZE , POINT_SIZE,0, (64*360) );
+ }
+ }
+ }
+ if (i < total_gaps-1)
+ nr_gap++;
+ }
+ }
+ else
+ max_num=tsnumber;
+
+ if (tsnumber>=min_tsn)
+ {
+ if (u_data->io->uoff)
+ diff = sack->secs - u_data->io->min_x;
+ else
+ diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
+ xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
+ yvalue = (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-POINT_SIZE -u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
+ if (xvalue >= LEFT_BORDER+u_data->io->offset &&
+ xvalue <= u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset &&
+ yvalue >= TOP_BORDER-u_data->io->offset-POINT_SIZE &&
+ yvalue <= u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ gdk_draw_arc(u_data->io->pixmap,red_gc,TRUE,
+ xvalue,
+ yvalue,
+ POINT_SIZE, POINT_SIZE,0, (64*360) );
+ }
+ }
+ }
+ tlist = g_list_next(tlist);
+ }
+ list = g_list_previous(list);
+ }
+ g_object_unref(G_OBJECT(red_gc));
+ g_object_unref(G_OBJECT(blue_gc));
+ g_object_unref(G_OBJECT(green_gc));
+}