1 /* sctp_graph_arwnd_dialog.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include "sctp_graph_arwnd_dialog.h"
11 #include <ui_sctp_graph_arwnd_dialog.h>
12 #include "sctp_assoc_analyse_dialog.h"
13 
14 #include <file.h>
15 #include <math.h>
16 #include <epan/dissectors/packet-sctp.h>
17 #include "epan/packet.h"
18 
19 #include "ui/tap-sctp-analysis.h"
20 
21 #include <ui/qt/utils/qt_ui_utils.h>
22 #include <ui/qt/widgets/qcustomplot.h>
23 #include "sctp_graph_dialog.h"
24 
SCTPGraphArwndDialog(QWidget * parent,const sctp_assoc_info_t * assoc,_capture_file * cf,int dir)25 SCTPGraphArwndDialog::SCTPGraphArwndDialog(QWidget *parent, const sctp_assoc_info_t *assoc,
26         _capture_file *cf, int dir) :
27     QDialog(parent),
28     ui(new Ui::SCTPGraphArwndDialog),
29     cap_file_(cf),
30     frame_num(0),
31     direction(dir),
32     startArwnd(0)
33 {
34     Q_ASSERT(assoc);
35     selected_assoc_id = assoc->assoc_id;
36 
37     ui->setupUi(this);
38     Qt::WindowFlags flags = Qt::Window | Qt::WindowSystemMenuHint
39             | Qt::WindowMinimizeButtonHint
40             | Qt::WindowMaximizeButtonHint
41             | Qt::WindowCloseButtonHint;
42     this->setWindowFlags(flags);
43     this->setWindowTitle(QString(tr("SCTP Data and Adv. Rec. Window over Time: %1 Port1 %2 Port2 %3"))
44             .arg(gchar_free_to_qstring(cf_get_display_name(cap_file_))).arg(assoc->port1).arg(assoc->port2));
45     if ((direction == 1 && assoc->n_array_tsn1 == 0) || (direction == 2 && assoc->n_array_tsn2 == 0)) {
46         QMessageBox msgBox;
47         msgBox.setText(tr("No Data Chunks sent"));
48         msgBox.exec();
49         return;
50     } else {
51         drawGraph(assoc);
52     }
53 }
54 
~SCTPGraphArwndDialog()55 SCTPGraphArwndDialog::~SCTPGraphArwndDialog()
56 {
57     delete ui;
58 }
59 
drawArwndGraph(const sctp_assoc_info_t * selected_assoc)60 void SCTPGraphArwndDialog::drawArwndGraph(const sctp_assoc_info_t *selected_assoc)
61 {
62     GList *listSACK = Q_NULLPTR, *tlist;
63     struct sack_chunk_header *sack_header;
64     struct nr_sack_chunk_header *nr_sack_header;
65     tsn_t *tsn;
66     guint8 type;
67     guint32 arwnd=0;
68 
69     if (direction == 1) {
70         listSACK = g_list_last(selected_assoc->sack1);
71         startArwnd = selected_assoc->arwnd2;
72     } else {
73         listSACK = g_list_last(selected_assoc->sack2);
74         startArwnd = selected_assoc->arwnd1;
75     }
76     bool detect_max_arwnd = (startArwnd == 0) ? true : false;
77 
78     while (listSACK) {
79         tsn = gxx_list_data(tsn_t*, listSACK);
80         tlist = g_list_first(tsn->tsns);
81         while (tlist) {
82             type = gxx_list_data(struct chunk_header *, tlist)->type;
83             if (type == SCTP_SACK_CHUNK_ID) {
84                 sack_header = gxx_list_data(struct sack_chunk_header *, tlist);
85                 arwnd = g_ntohl(sack_header->a_rwnd);
86             } else if (type == SCTP_NR_SACK_CHUNK_ID) {
87                 nr_sack_header = gxx_list_data(struct nr_sack_chunk_header *, tlist);
88                 arwnd = g_ntohl(nr_sack_header->a_rwnd);
89             }
90             if (detect_max_arwnd && startArwnd < arwnd) {
91                 startArwnd = arwnd;
92             }
93             ya.append(arwnd);
94             xa.append(tsn->secs + tsn->usecs/1000000.0);
95             fa.append(tsn->frame_number);
96             tlist = gxx_list_next(tlist);
97         }
98         listSACK = gxx_list_previous(listSACK);
99     }
100 
101     QCPScatterStyle myScatter;
102     myScatter.setShape(QCPScatterStyle::ssCircle);
103     myScatter.setSize(3);
104 
105     // create graph and assign data to it:
106 
107     // Add Arwnd graph
108     if (xa.size() > 0) {
109         QCPGraph *gr = ui->sctpPlot->addGraph(ui->sctpPlot->xAxis, ui->sctpPlot->yAxis);
110         gr->setName(QString(tr("Arwnd")));
111         myScatter.setPen(QPen(Qt::red));
112         myScatter.setBrush(Qt::red);
113         ui->sctpPlot->graph(0)->setScatterStyle(myScatter);
114         ui->sctpPlot->graph(0)->setLineStyle(QCPGraph::lsNone);
115         ui->sctpPlot->graph(0)->setData(xa, ya);
116     }
117 
118     ui->sctpPlot->xAxis->setLabel(tr("time [secs]"));
119     ui->sctpPlot->yAxis->setLabel(tr("Advertised Receiver Window [Bytes]"));
120 
121     // set axes ranges, so we see all data:
122     QCPRange myXArwndRange(0, (selected_assoc->max_secs+1));
123    // QCPRange myXArwndRange(0, 1);
124     QCPRange myYArwndRange(0, startArwnd);
125     ui->sctpPlot->xAxis->setRange(myXArwndRange);
126     ui->sctpPlot->yAxis->setRange(myYArwndRange);
127 }
128 
129 
drawGraph(const sctp_assoc_info_t * selected_assoc)130 void SCTPGraphArwndDialog::drawGraph(const sctp_assoc_info_t *selected_assoc)
131 {
132     ui->sctpPlot->clearGraphs();
133     drawArwndGraph(selected_assoc);
134     ui->sctpPlot->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectPlottables);
135     ui->sctpPlot->axisRect(0)->setRangeZoomAxes(ui->sctpPlot->xAxis, ui->sctpPlot->yAxis);
136     ui->sctpPlot->axisRect(0)->setRangeZoom(Qt::Horizontal);
137     connect(ui->sctpPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*, QMouseEvent*)));
138     ui->sctpPlot->replot();
139 }
140 
141 
on_pushButton_4_clicked()142 void SCTPGraphArwndDialog::on_pushButton_4_clicked()
143 {
144     const sctp_assoc_info_t* selected_assoc = SCTPAssocAnalyseDialog::findAssoc(this, selected_assoc_id);
145     if (!selected_assoc) return;
146 
147     ui->sctpPlot->xAxis->setRange(selected_assoc->min_secs+selected_assoc->min_usecs/1000000.0, selected_assoc->max_secs+selected_assoc->max_usecs/1000000.0);
148     ui->sctpPlot->yAxis->setRange(0, startArwnd);
149     ui->sctpPlot->replot();
150 }
151 
graphClicked(QCPAbstractPlottable * plottable,QMouseEvent * event)152 void SCTPGraphArwndDialog::graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event)
153 {
154     if (plottable->name().contains("Arwnd", Qt::CaseInsensitive)) {
155         double times = ui->sctpPlot->xAxis->pixelToCoord(event->pos().x());
156         int i=0;
157         for (i = 0; i < xa.size(); i++) {
158             if (times <= xa.value(i)) {
159                 frame_num = fa.at(i);
160                 break;
161             }
162         }
163         if (cap_file_ && frame_num > 0) {
164             cf_goto_frame(cap_file_, frame_num);
165         }
166 
167         ui->hintLabel->setText(QString(tr("<small><i>Graph %1: a_rwnd=%2 Time=%3 secs </i></small>"))
168                                .arg(plottable->name())
169                                .arg(ya.value(i))
170                                .arg(xa.value(i)));
171     }
172 }
173 
174 
on_saveButton_clicked()175 void SCTPGraphArwndDialog::on_saveButton_clicked()
176 {
177     SCTPGraphDialog::save_graph(this, ui->sctpPlot);
178 }
179